1 /*
2  *  Single source autogenerated distributable for Duktape 2.3.0.
3  *
4  *  Git commit d7fdb67f18561a50e06bafd196c6b423af9ad6fe (v2.3.0).
5  *  Git branch master.
6  *
7  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
8  *  licensing information.
9  */
10 
11 /* LICENSE.txt */
12 /*
13 *  ===============
14 *  Duktape license
15 *  ===============
16 *
17 *  (http://opensource.org/licenses/MIT)
18 *
19 *  Copyright (c) 2013-2018 by Duktape authors (see AUTHORS.rst)
20 *
21 *  Permission is hereby granted, free of charge, to any person obtaining a copy
22 *  of this software and associated documentation files (the "Software"), to deal
23 *  in the Software without restriction, including without limitation the rights
24 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 *  copies of the Software, and to permit persons to whom the Software is
26 *  furnished to do so, subject to the following conditions:
27 *
28 *  The above copyright notice and this permission notice shall be included in
29 *  all copies or substantial portions of the Software.
30 *
31 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 *  THE SOFTWARE.
38 */
39 
40 /* AUTHORS.rst */
41 /*
42 *  ===============
43 *  Duktape authors
44 *  ===============
45 *
46 *  Copyright
47 *  =========
48 *
49 *  Duktape copyrights are held by its authors.  Each author has a copyright
50 *  to their contribution, and agrees to irrevocably license the contribution
51 *  under the Duktape ``LICENSE.txt``.
52 *
53 *  Authors
54 *  =======
55 *
56 *  Please include an e-mail address, a link to your GitHub profile, or something
57 *  similar to allow your contribution to be identified accurately.
58 *
59 *  The following people have contributed code, website contents, or Wiki contents,
60 *  and agreed to irrevocably license their contributions under the Duktape
61 *  ``LICENSE.txt`` (in order of appearance):
62 *
63 *  * Sami Vaarala <sami.vaarala@iki.fi>
64 *  * Niki Dobrev
65 *  * Andreas \u00d6man <andreas@lonelycoder.com>
66 *  * L\u00e1szl\u00f3 Lang\u00f3 <llango.u-szeged@partner.samsung.com>
67 *  * Legimet <legimet.calc@gmail.com>
68 *  * Karl Skomski <karl@skomski.com>
69 *  * Bruce Pascoe <fatcerberus1@gmail.com>
70 *  * Ren\u00e9 Hollander <rene@rene8888.at>
71 *  * Julien Hamaide (https://github.com/crazyjul)
72 *  * Sebastian G\u00f6tte (https://github.com/jaseg)
73 *  * Tomasz Magulski (https://github.com/magul)
74 *  * \D. Bohdan (https://github.com/dbohdan)
75 *  * Ond\u0159ej Jirman (https://github.com/megous)
76 *  * Sa\u00fal Ibarra Corretg\u00e9 <saghul@gmail.com>
77 *  * Jeremy HU <huxingyi@msn.com>
78 *  * Ole Andr\u00e9 Vadla Ravn\u00e5s (https://github.com/oleavr)
79 *  * Harold Brenes (https://github.com/harold-b)
80 *  * Oliver Crow (https://github.com/ocrow)
81 *  * Jakub Ch\u0142api\u0144ski (https://github.com/jchlapinski)
82 *  * Brett Vickers (https://github.com/beevik)
83 *  * Dominik Okwieka (https://github.com/okitec)
84 *  * Remko Tron\u00e7on (https://el-tramo.be)
85 *  * Romero Malaquias (rbsm@ic.ufal.br)
86 *  * Michael Drake <michael.drake@codethink.co.uk>
87 *  * Steven Don (https://github.com/shdon)
88 *  * Simon Stone (https://github.com/sstone1)
89 *  * \J. McC. (https://github.com/jmhmccr)
90 *  * Jakub Nowakowski (https://github.com/jimvonmoon)
91 *  * Tommy Nguyen (https://github.com/tn0502)
92 *  * Fabrice Fontaine (https://github.com/ffontaine)
93 *  * Christopher Hiller (https://github.com/boneskull)
94 *  * Gonzalo Diethelm (https://github.com/gonzus)
95 *  * Michal Kasperek (https://github.com/michalkas)
96 *  * Andrew Janke (https://github.com/apjanke)
97 *  * Steve Fan (https://github.com/stevefan1999)
98 *
99 *  Other contributions
100 *  ===================
101 *
102 *  The following people have contributed something other than code (e.g. reported
103 *  bugs, provided ideas, etc; roughly in order of appearance):
104 *
105 *  * Greg Burns
106 *  * Anthony Rabine
107 *  * Carlos Costa
108 *  * Aur\u00e9lien Bouilland
109 *  * Preet Desai (Pris Matic)
110 *  * judofyr (http://www.reddit.com/user/judofyr)
111 *  * Jason Woofenden
112 *  * Micha\u0142 Przyby\u015b
113 *  * Anthony Howe
114 *  * Conrad Pankoff
115 *  * Jim Schimpf
116 *  * Rajaran Gaunker (https://github.com/zimbabao)
117 *  * Andreas \u00d6man
118 *  * Doug Sanden
119 *  * Josh Engebretson (https://github.com/JoshEngebretson)
120 *  * Remo Eichenberger (https://github.com/remoe)
121 *  * Mamod Mehyar (https://github.com/mamod)
122 *  * David Demelier (https://github.com/markand)
123 *  * Tim Caswell (https://github.com/creationix)
124 *  * Mitchell Blank Jr (https://github.com/mitchblank)
125 *  * https://github.com/yushli
126 *  * Seo Sanghyeon (https://github.com/sanxiyn)
127 *  * Han ChoongWoo (https://github.com/tunz)
128 *  * Joshua Peek (https://github.com/josh)
129 *  * Bruce E. Pascoe (https://github.com/fatcerberus)
130 *  * https://github.com/Kelledin
131 *  * https://github.com/sstruchtrup
132 *  * Michael Drake (https://github.com/tlsa)
133 *  * https://github.com/chris-y
134 *  * Laurent Zubiaur (https://github.com/lzubiaur)
135 *  * Neil Kolban (https://github.com/nkolban)
136 *  * Wilhelm Wanecek (https://github.com/wanecek)
137 *  * Andrew Janke (https://github.com/apjanke)
138 *
139 *  If you are accidentally missing from this list, send me an e-mail
140 *  (``sami.vaarala@iki.fi``) and I'll fix the omission.
141 */
142 
143 #line 1 "duk_replacements.c"
144 /*
145  *  Replacements for missing platform functions.
146  *
147  *  Unlike the originals, fpclassify() and signbit() replacements don't
148  *  work on any floating point types, only doubles.  The C typing here
149  *  mimics the standard prototypes.
150  */
151 
152 /* #include duk_internal.h */
153 #line 1 "duk_internal.h"
154 /*
155  *  Top-level include file to be used for all (internal) source files.
156  *
157  *  Source files should not include individual header files, as they
158  *  have not been designed to be individually included.
159  */
160 
161 #if !defined(DUK_INTERNAL_H_INCLUDED)
162 #define DUK_INTERNAL_H_INCLUDED
163 
164 /*
165  *  The 'duktape.h' header provides the public API, but also handles all
166  *  compiler and platform specific feature detection, Duktape feature
167  *  resolution, inclusion of system headers, etc.  These have been merged
168  *  because the public API is also dependent on e.g. detecting appropriate
169  *  C types which is quite platform/compiler specific especially for a non-C99
170  *  build.  The public API is also dependent on the resolved feature set.
171  *
172  *  Some actions taken by the merged header (such as including system headers)
173  *  are not appropriate for building a user application.  The define
174  *  DUK_COMPILING_DUKTAPE allows the merged header to skip/include some
175  *  sections depending on what is being built.
176  */
177 
178 #define DUK_COMPILING_DUKTAPE
179 #include "duktape.h"
180 
181 /*
182  *  User declarations, e.g. prototypes for user functions used by Duktape
183  *  macros.
184  */
185 
186 DUK_USE_USER_DECLARE()
187 
188 /*
189  *  Duktape includes (other than duk_features.h)
190  *
191  *  The header files expect to be included in an order which satisfies header
192  *  dependencies correctly (the headers themselves don't include any other
193  *  includes).  Forward declarations are used to break circular struct/typedef
194  *  dependencies.
195  */
196 
197 /* #include duk_dblunion.h */
198 #line 1 "duk_dblunion.h"
199 /*
200  *  Union to access IEEE double memory representation, indexes for double
201  *  memory representation, and some macros for double manipulation.
202  *
203  *  Also used by packed duk_tval.  Use a union for bit manipulation to
204  *  minimize aliasing issues in practice.  The C99 standard does not
205  *  guarantee that this should work, but it's a very widely supported
206  *  practice for low level manipulation.
207  *
208  *  IEEE double format summary:
209  *
210  *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
211  *       A        B        C        D        E        F        G        H
212  *
213  *    s       sign bit
214  *    eee...  exponent field
215  *    fff...  fraction
216  *
217  *  See http://en.wikipedia.org/wiki/Double_precision_floating-point_format.
218  *
219  *  NaNs are represented as exponent 0x7ff and mantissa != 0.  The NaN is a
220  *  signaling NaN when the highest bit of the mantissa is zero, and a quiet
221  *  NaN when the highest bit is set.
222  *
223  *  At least three memory layouts are relevant here:
224  *
225  *    A B C D E F G H    Big endian (e.g. 68k)           DUK_USE_DOUBLE_BE
226  *    H G F E D C B A    Little endian (e.g. x86)        DUK_USE_DOUBLE_LE
227  *    D C B A H G F E    Mixed/cross endian (e.g. ARM)   DUK_USE_DOUBLE_ME
228  *
229  *  ARM is a special case: ARM double values are in mixed/cross endian
230  *  format while ARM duk_uint64_t values are in standard little endian
231  *  format (H G F E D C B A).  When a double is read as a duk_uint64_t
232  *  from memory, the register will contain the (logical) value
233  *  E F G H A B C D.  This requires some special handling below.
234  *
235  *  Indexes of various types (8-bit, 16-bit, 32-bit) in memory relative to
236  *  the logical (big endian) order:
237  *
238  *  byte order      duk_uint8_t    duk_uint16_t     duk_uint32_t
239  *    BE             01234567         0123               01
240  *    LE             76543210         3210               10
241  *    ME (ARM)       32107654         1032               01
242  *
243  *  Some processors may alter NaN values in a floating point load+store.
244  *  For instance, on X86 a FLD + FSTP may convert a signaling NaN to a
245  *  quiet one.  This is catastrophic when NaN space is used in packed
246  *  duk_tval values.  See: misc/clang_aliasing.c.
247  */
248 
249 #if !defined(DUK_DBLUNION_H_INCLUDED)
250 #define DUK_DBLUNION_H_INCLUDED
251 
252 /*
253  *  Union for accessing double parts, also serves as packed duk_tval
254  */
255 
256 union duk_double_union {
257 	double d;
258 	float f[2];
259 #if defined(DUK_USE_64BIT_OPS)
260 	duk_uint64_t ull[1];
261 #endif
262 	duk_uint32_t ui[2];
263 	duk_uint16_t us[4];
264 	duk_uint8_t uc[8];
265 #if defined(DUK_USE_PACKED_TVAL)
266 	void *vp[2];  /* used by packed duk_tval, assumes sizeof(void *) == 4 */
267 #endif
268 };
269 
270 typedef union duk_double_union duk_double_union;
271 
272 /*
273  *  Indexes of various types with respect to big endian (logical) layout
274  */
275 
276 #if defined(DUK_USE_DOUBLE_LE)
277 #if defined(DUK_USE_64BIT_OPS)
278 #define DUK_DBL_IDX_ULL0   0
279 #endif
280 #define DUK_DBL_IDX_UI0    1
281 #define DUK_DBL_IDX_UI1    0
282 #define DUK_DBL_IDX_US0    3
283 #define DUK_DBL_IDX_US1    2
284 #define DUK_DBL_IDX_US2    1
285 #define DUK_DBL_IDX_US3    0
286 #define DUK_DBL_IDX_UC0    7
287 #define DUK_DBL_IDX_UC1    6
288 #define DUK_DBL_IDX_UC2    5
289 #define DUK_DBL_IDX_UC3    4
290 #define DUK_DBL_IDX_UC4    3
291 #define DUK_DBL_IDX_UC5    2
292 #define DUK_DBL_IDX_UC6    1
293 #define DUK_DBL_IDX_UC7    0
294 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
295 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
296 #elif defined(DUK_USE_DOUBLE_BE)
297 #if defined(DUK_USE_64BIT_OPS)
298 #define DUK_DBL_IDX_ULL0   0
299 #endif
300 #define DUK_DBL_IDX_UI0    0
301 #define DUK_DBL_IDX_UI1    1
302 #define DUK_DBL_IDX_US0    0
303 #define DUK_DBL_IDX_US1    1
304 #define DUK_DBL_IDX_US2    2
305 #define DUK_DBL_IDX_US3    3
306 #define DUK_DBL_IDX_UC0    0
307 #define DUK_DBL_IDX_UC1    1
308 #define DUK_DBL_IDX_UC2    2
309 #define DUK_DBL_IDX_UC3    3
310 #define DUK_DBL_IDX_UC4    4
311 #define DUK_DBL_IDX_UC5    5
312 #define DUK_DBL_IDX_UC6    6
313 #define DUK_DBL_IDX_UC7    7
314 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
315 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
316 #elif defined(DUK_USE_DOUBLE_ME)
317 #if defined(DUK_USE_64BIT_OPS)
318 #define DUK_DBL_IDX_ULL0   0  /* not directly applicable, byte order differs from a double */
319 #endif
320 #define DUK_DBL_IDX_UI0    0
321 #define DUK_DBL_IDX_UI1    1
322 #define DUK_DBL_IDX_US0    1
323 #define DUK_DBL_IDX_US1    0
324 #define DUK_DBL_IDX_US2    3
325 #define DUK_DBL_IDX_US3    2
326 #define DUK_DBL_IDX_UC0    3
327 #define DUK_DBL_IDX_UC1    2
328 #define DUK_DBL_IDX_UC2    1
329 #define DUK_DBL_IDX_UC3    0
330 #define DUK_DBL_IDX_UC4    7
331 #define DUK_DBL_IDX_UC5    6
332 #define DUK_DBL_IDX_UC6    5
333 #define DUK_DBL_IDX_UC7    4
334 #define DUK_DBL_IDX_VP0    DUK_DBL_IDX_UI0  /* packed tval */
335 #define DUK_DBL_IDX_VP1    DUK_DBL_IDX_UI1  /* packed tval */
336 #else
337 #error internal error
338 #endif
339 
340 /*
341  *  Helper macros for reading/writing memory representation parts, used
342  *  by duk_numconv.c and duk_tval.h.
343  */
344 
345 #define DUK_DBLUNION_SET_DOUBLE(u,v)  do {  \
346 		(u)->d = (v); \
347 	} while (0)
348 
349 #define DUK_DBLUNION_SET_HIGH32(u,v)  do {  \
350 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
351 	} while (0)
352 
353 #if defined(DUK_USE_64BIT_OPS)
354 #if defined(DUK_USE_DOUBLE_ME)
355 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
356 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
357 	} while (0)
358 #else
359 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
360 		(u)->ull[DUK_DBL_IDX_ULL0] = ((duk_uint64_t) (v)) << 32; \
361 	} while (0)
362 #endif
363 #else  /* DUK_USE_64BIT_OPS */
364 #define DUK_DBLUNION_SET_HIGH32_ZERO_LOW32(u,v)  do { \
365 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) (v); \
366 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0; \
367 	} while (0)
368 #endif  /* DUK_USE_64BIT_OPS */
369 
370 #define DUK_DBLUNION_SET_LOW32(u,v)  do {  \
371 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
372 	} while (0)
373 
374 #define DUK_DBLUNION_GET_DOUBLE(u)  ((u)->d)
375 #define DUK_DBLUNION_GET_HIGH32(u)  ((u)->ui[DUK_DBL_IDX_UI0])
376 #define DUK_DBLUNION_GET_LOW32(u)   ((u)->ui[DUK_DBL_IDX_UI1])
377 
378 #if defined(DUK_USE_64BIT_OPS)
379 #if defined(DUK_USE_DOUBLE_ME)
380 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
381 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) ((v) >> 32); \
382 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (v); \
383 	} while (0)
384 #define DUK_DBLUNION_GET_UINT64(u) \
385 	((((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI0]) << 32) | \
386 	 ((duk_uint64_t) (u)->ui[DUK_DBL_IDX_UI1]))
387 #else
388 #define DUK_DBLUNION_SET_UINT64(u,v)  do { \
389 		(u)->ull[DUK_DBL_IDX_ULL0] = (duk_uint64_t) (v); \
390 	} while (0)
391 #define DUK_DBLUNION_GET_UINT64(u)  ((u)->ull[DUK_DBL_IDX_ULL0])
392 #endif
393 #define DUK_DBLUNION_SET_INT64(u,v) DUK_DBLUNION_SET_UINT64((u), (duk_uint64_t) (v))
394 #define DUK_DBLUNION_GET_INT64(u)   ((duk_int64_t) DUK_DBLUNION_GET_UINT64((u)))
395 #endif  /* DUK_USE_64BIT_OPS */
396 
397 /*
398  *  Double NaN manipulation macros related to NaN normalization needed when
399  *  using the packed duk_tval representation.  NaN normalization is necessary
400  *  to keep double values compatible with the duk_tval format.
401  *
402  *  When packed duk_tval is used, the NaN space is used to store pointers
403  *  and other tagged values in addition to NaNs.  Actual NaNs are normalized
404  *  to a specific quiet NaN.  The macros below are used by the implementation
405  *  to check and normalize NaN values when they might be created.  The macros
406  *  are essentially NOPs when the non-packed duk_tval representation is used.
407  *
408  *  A FULL check is exact and checks all bits.  A NOTFULL check is used by
409  *  the packed duk_tval and works correctly for all NaNs except those that
410  *  begin with 0x7ff0.  Since the 'normalized NaN' values used with packed
411  *  duk_tval begin with 0x7ff8, the partial check is reliable when packed
412  *  duk_tval is used.  The 0x7ff8 prefix means the normalized NaN will be a
413  *  quiet NaN regardless of its remaining lower bits.
414  *
415  *  The ME variant below is specifically for ARM byte order, which has the
416  *  feature that while doubles have a mixed byte order (32107654), unsigned
417  *  long long values has a little endian byte order (76543210).  When writing
418  *  a logical double value through a ULL pointer, the 32-bit words need to be
419  *  swapped; hence the #if defined()s below for ULL writes with DUK_USE_DOUBLE_ME.
420  *  This is not full ARM support but suffices for some environments.
421  */
422 
423 #if defined(DUK_USE_64BIT_OPS)
424 #if defined(DUK_USE_DOUBLE_ME)
425 /* Macros for 64-bit ops + mixed endian doubles. */
426 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
427 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x000000007ff80000); \
428 	} while (0)
429 #define DUK__DBLUNION_IS_NAN_FULL(u) \
430 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000)) && \
431 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0xffffffff000fffff)) != 0))
432 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
433 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff80000))
434 #define DUK__DBLUNION_IS_ANYINF(u) \
435 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x000000007ff00000))
436 #define DUK__DBLUNION_IS_POSINF(u) \
437 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x000000007ff00000))
438 #define DUK__DBLUNION_IS_NEGINF(u) \
439 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x00000000fff00000))
440 #define DUK__DBLUNION_IS_ANYZERO(u) \
441 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0xffffffff7fffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
442 #define DUK__DBLUNION_IS_POSZERO(u) \
443 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
444 #define DUK__DBLUNION_IS_NEGZERO(u) \
445 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000080000000))
446 #else
447 /* Macros for 64-bit ops + big/little endian doubles. */
448 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
449 		(u)->ull[DUK_DBL_IDX_ULL0] = DUK_U64_CONSTANT(0x7ff8000000000000); \
450 	} while (0)
451 #define DUK__DBLUNION_IS_NAN_FULL(u) \
452 	((((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000)) && \
453 	 ((((u)->ull[DUK_DBL_IDX_ULL0]) & DUK_U64_CONSTANT(0x000fffffffffffff)) != 0))
454 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
455 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff8000000000000))
456 #define DUK__DBLUNION_IS_ANYINF(u) \
457 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x7ff0000000000000))
458 #define DUK__DBLUNION_IS_POSINF(u) \
459 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x7ff0000000000000))
460 #define DUK__DBLUNION_IS_NEGINF(u) \
461 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0xfff0000000000000))
462 #define DUK__DBLUNION_IS_ANYZERO(u) \
463 	(((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7fffffffffffffff)) == DUK_U64_CONSTANT(0x0000000000000000))
464 #define DUK__DBLUNION_IS_POSZERO(u) \
465 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x0000000000000000))
466 #define DUK__DBLUNION_IS_NEGZERO(u) \
467 	((u)->ull[DUK_DBL_IDX_ULL0] == DUK_U64_CONSTANT(0x8000000000000000))
468 #endif
469 #else  /* DUK_USE_64BIT_OPS */
470 /* Macros for no 64-bit ops, any endianness. */
471 #define DUK__DBLUNION_SET_NAN_FULL(u)  do { \
472 		(u)->ui[DUK_DBL_IDX_UI0] = (duk_uint32_t) 0x7ff80000UL; \
473 		(u)->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) 0x00000000UL; \
474 	} while (0)
475 #define DUK__DBLUNION_IS_NAN_FULL(u) \
476 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL) && \
477 	 (((u)->ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) != 0 || \
478           (u)->ui[DUK_DBL_IDX_UI1] != 0))
479 #define DUK__DBLUNION_IS_NORMALIZED_NAN_FULL(u) \
480 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff80000UL) && \
481 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
482 #define DUK__DBLUNION_IS_ANYINF(u) \
483 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x7ff00000UL) && \
484 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
485 #define DUK__DBLUNION_IS_POSINF(u) \
486 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x7ff00000UL) && \
487 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
488 #define DUK__DBLUNION_IS_NEGINF(u) \
489 	(((u)->ui[DUK_DBL_IDX_UI0] == 0xfff00000UL) && \
490 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
491 #define DUK__DBLUNION_IS_ANYZERO(u) \
492 	((((u)->ui[DUK_DBL_IDX_UI0] & 0x7fffffffUL) == 0x00000000UL) && \
493 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
494 #define DUK__DBLUNION_IS_POSZERO(u) \
495 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x00000000UL) && \
496 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
497 #define DUK__DBLUNION_IS_NEGZERO(u) \
498 	(((u)->ui[DUK_DBL_IDX_UI0] == 0x80000000UL) && \
499 	 ((u)->ui[DUK_DBL_IDX_UI1] == 0x00000000UL))
500 #endif  /* DUK_USE_64BIT_OPS */
501 
502 #define DUK__DBLUNION_SET_NAN_NOTFULL(u)  do { \
503 		(u)->us[DUK_DBL_IDX_US0] = 0x7ff8UL; \
504 	} while (0)
505 
506 #define DUK__DBLUNION_IS_NAN_NOTFULL(u) \
507 	/* E == 0x7ff, topmost four bits of F != 0 => assume NaN */ \
508 	((((u)->us[DUK_DBL_IDX_US0] & 0x7ff0UL) == 0x7ff0UL) && \
509 	 (((u)->us[DUK_DBL_IDX_US0] & 0x000fUL) != 0x0000UL))
510 
511 #define DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL(u) \
512 	/* E == 0x7ff, F == 8 => normalized NaN */ \
513 	((u)->us[DUK_DBL_IDX_US0] == 0x7ff8UL)
514 
515 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL(u)  do { \
516 		if (DUK__DBLUNION_IS_NAN_FULL((u))) { \
517 			DUK__DBLUNION_SET_NAN_FULL((u)); \
518 		} \
519 	} while (0)
520 
521 #define DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL(u)  do { \
522 		if (DUK__DBLUNION_IS_NAN_NOTFULL((u))) { \
523 			DUK__DBLUNION_SET_NAN_NOTFULL((u)); \
524 		} \
525 	} while (0)
526 
527 /* Concrete macros for NaN handling used by the implementation internals.
528  * Chosen so that they match the duk_tval representation: with a packed
529  * duk_tval, ensure NaNs are properly normalized; with a non-packed duk_tval
530  * these are essentially NOPs.
531  */
532 
533 #if defined(DUK_USE_PACKED_TVAL)
534 #if defined(DUK_USE_FULL_TVAL)
535 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_FULL((u))
536 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))
537 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_FULL((u))
538 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_FULL((d))
539 #else
540 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  DUK__DBLUNION_NORMALIZE_NAN_CHECK_NOTFULL((u))
541 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_NOTFULL((u))
542 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NORMALIZED_NAN_NOTFULL((u))
543 #define DUK_DBLUNION_SET_NAN(d)              DUK__DBLUNION_SET_NAN_NOTFULL((d))
544 #endif
545 #define DUK_DBLUNION_IS_NORMALIZED(u) \
546 	(!DUK_DBLUNION_IS_NAN((u)) ||  /* either not a NaN */ \
547 	 DUK_DBLUNION_IS_NORMALIZED_NAN((u)))  /* or is a normalized NaN */
548 #else  /* DUK_USE_PACKED_TVAL */
549 #define DUK_DBLUNION_NORMALIZE_NAN_CHECK(u)  /* nop: no need to normalize */
550 #define DUK_DBLUNION_IS_NAN(u)               DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
551 #define DUK_DBLUNION_IS_NORMALIZED_NAN(u)    DUK__DBLUNION_IS_NAN_FULL((u))  /* (DUK_ISNAN((u)->d)) */
552 #define DUK_DBLUNION_IS_NORMALIZED(u)        1  /* all doubles are considered normalized */
553 #define DUK_DBLUNION_SET_NAN(u)  do { \
554 		/* in non-packed representation we don't care about which NaN is used */ \
555 		(u)->d = DUK_DOUBLE_NAN; \
556 	} while (0)
557 #endif  /* DUK_USE_PACKED_TVAL */
558 
559 #define DUK_DBLUNION_IS_ANYINF(u) DUK__DBLUNION_IS_ANYINF((u))
560 #define DUK_DBLUNION_IS_POSINF(u) DUK__DBLUNION_IS_POSINF((u))
561 #define DUK_DBLUNION_IS_NEGINF(u) DUK__DBLUNION_IS_NEGINF((u))
562 
563 #define DUK_DBLUNION_IS_ANYZERO(u) DUK__DBLUNION_IS_ANYZERO((u))
564 #define DUK_DBLUNION_IS_POSZERO(u) DUK__DBLUNION_IS_POSZERO((u))
565 #define DUK_DBLUNION_IS_NEGZERO(u) DUK__DBLUNION_IS_NEGZERO((u))
566 
567 /* XXX: native 64-bit byteswaps when available */
568 
569 /* 64-bit byteswap, same operation independent of target endianness. */
570 #define DUK_DBLUNION_BSWAP64(u) do { \
571 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
572 		duk__bswaptmp1 = (u)->ui[0]; \
573 		duk__bswaptmp2 = (u)->ui[1]; \
574 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
575 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
576 		(u)->ui[0] = duk__bswaptmp2; \
577 		(u)->ui[1] = duk__bswaptmp1; \
578 	} while (0)
579 
580 /* Byteswap an IEEE double in the duk_double_union from host to network
581  * order.  For a big endian target this is a no-op.
582  */
583 #if defined(DUK_USE_DOUBLE_LE)
584 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
585 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
586 		duk__bswaptmp1 = (u)->ui[0]; \
587 		duk__bswaptmp2 = (u)->ui[1]; \
588 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
589 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
590 		(u)->ui[0] = duk__bswaptmp2; \
591 		(u)->ui[1] = duk__bswaptmp1; \
592 	} while (0)
593 #elif defined(DUK_USE_DOUBLE_ME)
594 #define DUK_DBLUNION_DOUBLE_HTON(u) do { \
595 		duk_uint32_t duk__bswaptmp1, duk__bswaptmp2; \
596 		duk__bswaptmp1 = (u)->ui[0]; \
597 		duk__bswaptmp2 = (u)->ui[1]; \
598 		duk__bswaptmp1 = DUK_BSWAP32(duk__bswaptmp1); \
599 		duk__bswaptmp2 = DUK_BSWAP32(duk__bswaptmp2); \
600 		(u)->ui[0] = duk__bswaptmp1; \
601 		(u)->ui[1] = duk__bswaptmp2; \
602 	} while (0)
603 #elif defined(DUK_USE_DOUBLE_BE)
604 #define DUK_DBLUNION_DOUBLE_HTON(u) do { } while (0)
605 #else
606 #error internal error, double endianness insane
607 #endif
608 
609 /* Reverse operation is the same. */
610 #define DUK_DBLUNION_DOUBLE_NTOH(u) DUK_DBLUNION_DOUBLE_HTON((u))
611 
612 /* Some sign bit helpers. */
613 #if defined(DUK_USE_64BIT_OPS)
614 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000)) != 0)
615 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ull[DUK_DBL_IDX_ULL0] >> 63U))
616 #else
617 #define DUK_DBLUNION_HAS_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] & 0x80000000UL) != 0)
618 #define DUK_DBLUNION_GET_SIGNBIT(u) (((u)->ui[DUK_DBL_IDX_UI0] >> 31U))
619 #endif
620 
621 #endif  /* DUK_DBLUNION_H_INCLUDED */
622 /* #include duk_replacements.h */
623 #line 1 "duk_replacements.h"
624 #if !defined(DUK_REPLACEMENTS_H_INCLUDED)
625 #define DUK_REPLACEMENTS_H_INCLUDED
626 
627 #if !defined(DUK_SINGLE_FILE)
628 #if defined(DUK_USE_COMPUTED_INFINITY)
629 DUK_INTERNAL_DECL double duk_computed_infinity;
630 #endif
631 #if defined(DUK_USE_COMPUTED_NAN)
632 DUK_INTERNAL_DECL double duk_computed_nan;
633 #endif
634 #endif  /* !DUK_SINGLE_FILE */
635 
636 #if defined(DUK_USE_REPL_FPCLASSIFY)
637 DUK_INTERNAL_DECL int duk_repl_fpclassify(double x);
638 #endif
639 #if defined(DUK_USE_REPL_SIGNBIT)
640 DUK_INTERNAL_DECL int duk_repl_signbit(double x);
641 #endif
642 #if defined(DUK_USE_REPL_ISFINITE)
643 DUK_INTERNAL_DECL int duk_repl_isfinite(double x);
644 #endif
645 #if defined(DUK_USE_REPL_ISNAN)
646 DUK_INTERNAL_DECL int duk_repl_isnan(double x);
647 #endif
648 #if defined(DUK_USE_REPL_ISINF)
649 DUK_INTERNAL_DECL int duk_repl_isinf(double x);
650 #endif
651 
652 #endif  /* DUK_REPLACEMENTS_H_INCLUDED */
653 /* #include duk_jmpbuf.h */
654 #line 1 "duk_jmpbuf.h"
655 /*
656  *  Wrapper for jmp_buf.
657  *
658  *  This is used because jmp_buf is an array type for backward compatibility.
659  *  Wrapping jmp_buf in a struct makes pointer references, sizeof, etc,
660  *  behave more intuitively.
661  *
662  *  http://en.wikipedia.org/wiki/Setjmp.h#Member_types
663  */
664 
665 #if !defined(DUK_JMPBUF_H_INCLUDED)
666 #define DUK_JMPBUF_H_INCLUDED
667 
668 #if defined(DUK_USE_CPP_EXCEPTIONS)
669 struct duk_jmpbuf {
670 	duk_small_int_t dummy;  /* unused */
671 };
672 #else
673 struct duk_jmpbuf {
674 	DUK_JMPBUF_TYPE jb;
675 };
676 #endif
677 
678 #endif  /* DUK_JMPBUF_H_INCLUDED */
679 /* #include duk_exception.h */
680 #line 1 "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 #line 1 "duk_forwdecl.h"
713 /*
714  *  Forward declarations for all Duktape structures.
715  */
716 
717 #if !defined(DUK_FORWDECL_H_INCLUDED)
718 #define DUK_FORWDECL_H_INCLUDED
719 
720 /*
721  *  Forward declarations
722  */
723 
724 #if defined(DUK_USE_CPP_EXCEPTIONS)
725 class duk_internal_exception;
726 #else
727 struct duk_jmpbuf;
728 #endif
729 
730 /* duk_tval intentionally skipped */
731 struct duk_heaphdr;
732 struct duk_heaphdr_string;
733 struct duk_harray;
734 struct duk_hstring;
735 struct duk_hstring_external;
736 struct duk_hobject;
737 struct duk_hcompfunc;
738 struct duk_hnatfunc;
739 struct duk_hboundfunc;
740 struct duk_hthread;
741 struct duk_hbufobj;
742 struct duk_hdecenv;
743 struct duk_hobjenv;
744 struct duk_hproxy;
745 struct duk_hbuffer;
746 struct duk_hbuffer_fixed;
747 struct duk_hbuffer_dynamic;
748 struct duk_hbuffer_external;
749 
750 struct duk_propaccessor;
751 union duk_propvalue;
752 struct duk_propdesc;
753 
754 struct duk_heap;
755 struct duk_breakpoint;
756 
757 struct duk_activation;
758 struct duk_catcher;
759 struct duk_ljstate;
760 struct duk_strcache_entry;
761 struct duk_litcache_entry;
762 struct duk_strtab_entry;
763 
764 #if defined(DUK_USE_DEBUG)
765 struct duk_fixedbuffer;
766 #endif
767 
768 struct duk_bitdecoder_ctx;
769 struct duk_bitencoder_ctx;
770 struct duk_bufwriter_ctx;
771 
772 struct duk_token;
773 struct duk_re_token;
774 struct duk_lexer_point;
775 struct duk_lexer_ctx;
776 struct duk_lexer_codepoint;
777 
778 struct duk_compiler_instr;
779 struct duk_compiler_func;
780 struct duk_compiler_ctx;
781 
782 struct duk_re_matcher_ctx;
783 struct duk_re_compiler_ctx;
784 
785 #if defined(DUK_USE_CPP_EXCEPTIONS)
786 /* no typedef */
787 #else
788 typedef struct duk_jmpbuf duk_jmpbuf;
789 #endif
790 
791 /* duk_tval intentionally skipped */
792 typedef struct duk_heaphdr duk_heaphdr;
793 typedef struct duk_heaphdr_string duk_heaphdr_string;
794 typedef struct duk_harray duk_harray;
795 typedef struct duk_hstring duk_hstring;
796 typedef struct duk_hstring_external duk_hstring_external;
797 typedef struct duk_hobject duk_hobject;
798 typedef struct duk_hcompfunc duk_hcompfunc;
799 typedef struct duk_hnatfunc duk_hnatfunc;
800 typedef struct duk_hboundfunc duk_hboundfunc;
801 typedef struct duk_hthread duk_hthread;
802 typedef struct duk_hbufobj duk_hbufobj;
803 typedef struct duk_hdecenv duk_hdecenv;
804 typedef struct duk_hobjenv duk_hobjenv;
805 typedef struct duk_hproxy duk_hproxy;
806 typedef struct duk_hbuffer duk_hbuffer;
807 typedef struct duk_hbuffer_fixed duk_hbuffer_fixed;
808 typedef struct duk_hbuffer_dynamic duk_hbuffer_dynamic;
809 typedef struct duk_hbuffer_external duk_hbuffer_external;
810 
811 typedef struct duk_propaccessor duk_propaccessor;
812 typedef union duk_propvalue duk_propvalue;
813 typedef struct duk_propdesc duk_propdesc;
814 
815 typedef struct duk_heap duk_heap;
816 typedef struct duk_breakpoint duk_breakpoint;
817 
818 typedef struct duk_activation duk_activation;
819 typedef struct duk_catcher duk_catcher;
820 typedef struct duk_ljstate duk_ljstate;
821 typedef struct duk_strcache_entry duk_strcache_entry;
822 typedef struct duk_litcache_entry duk_litcache_entry;
823 typedef struct duk_strtab_entry duk_strtab_entry;
824 
825 #if defined(DUK_USE_DEBUG)
826 typedef struct duk_fixedbuffer duk_fixedbuffer;
827 #endif
828 
829 typedef struct duk_bitdecoder_ctx duk_bitdecoder_ctx;
830 typedef struct duk_bitencoder_ctx duk_bitencoder_ctx;
831 typedef struct duk_bufwriter_ctx duk_bufwriter_ctx;
832 
833 typedef struct duk_token duk_token;
834 typedef struct duk_re_token duk_re_token;
835 typedef struct duk_lexer_point duk_lexer_point;
836 typedef struct duk_lexer_ctx duk_lexer_ctx;
837 typedef struct duk_lexer_codepoint duk_lexer_codepoint;
838 
839 typedef struct duk_compiler_instr duk_compiler_instr;
840 typedef struct duk_compiler_func duk_compiler_func;
841 typedef struct duk_compiler_ctx duk_compiler_ctx;
842 
843 typedef struct duk_re_matcher_ctx duk_re_matcher_ctx;
844 typedef struct duk_re_compiler_ctx duk_re_compiler_ctx;
845 
846 #endif  /* DUK_FORWDECL_H_INCLUDED */
847 /* #include duk_tval.h */
848 #line 1 "duk_tval.h"
849 /*
850  *  Tagged type definition (duk_tval) and accessor macros.
851  *
852  *  Access all fields through the accessor macros, as the representation
853  *  is quite tricky.
854  *
855  *  There are two packed type alternatives: an 8-byte representation
856  *  based on an IEEE double (preferred for compactness), and a 12-byte
857  *  representation (portability).  The latter is needed also in e.g.
858  *  64-bit environments (it usually pads to 16 bytes per value).
859  *
860  *  Selecting the tagged type format involves many trade-offs (memory
861  *  use, size and performance of generated code, portability, etc).
862  *
863  *  NB: because macro arguments are often expressions, macros should
864  *  avoid evaluating their argument more than once.
865  */
866 
867 #if !defined(DUK_TVAL_H_INCLUDED)
868 #define DUK_TVAL_H_INCLUDED
869 
870 /* sanity */
871 #if !defined(DUK_USE_DOUBLE_LE) && !defined(DUK_USE_DOUBLE_ME) && !defined(DUK_USE_DOUBLE_BE)
872 #error unsupported: cannot determine byte order variant
873 #endif
874 
875 #if defined(DUK_USE_PACKED_TVAL)
876 /* ======================================================================== */
877 
878 /*
879  *  Packed 8-byte representation
880  */
881 
882 /* use duk_double_union as duk_tval directly */
883 typedef union duk_double_union duk_tval;
884 typedef struct {
885 	duk_uint16_t a;
886 	duk_uint16_t b;
887 	duk_uint16_t c;
888 	duk_uint16_t d;
889 } duk_tval_unused;
890 
891 /* tags */
892 #define DUK_TAG_NORMALIZED_NAN    0x7ff8UL   /* the NaN variant we use */
893 /* avoid tag 0xfff0, no risk of confusion with negative infinity */
894 #define DUK_TAG_MIN               0xfff1UL
895 #if defined(DUK_USE_FASTINT)
896 #define DUK_TAG_FASTINT           0xfff1UL   /* embed: integer value */
897 #endif
898 #define DUK_TAG_UNUSED            0xfff2UL   /* marker; not actual tagged value */
899 #define DUK_TAG_UNDEFINED         0xfff3UL   /* embed: nothing */
900 #define DUK_TAG_NULL              0xfff4UL   /* embed: nothing */
901 #define DUK_TAG_BOOLEAN           0xfff5UL   /* embed: 0 or 1 (false or true) */
902 /* DUK_TAG_NUMBER would logically go here, but it has multiple 'tags' */
903 #define DUK_TAG_POINTER           0xfff6UL   /* embed: void ptr */
904 #define DUK_TAG_LIGHTFUNC         0xfff7UL   /* embed: func ptr */
905 #define DUK_TAG_STRING            0xfff8UL   /* embed: duk_hstring ptr */
906 #define DUK_TAG_OBJECT            0xfff9UL   /* embed: duk_hobject ptr */
907 #define DUK_TAG_BUFFER            0xfffaUL   /* embed: duk_hbuffer ptr */
908 #define DUK_TAG_MAX               0xfffaUL
909 
910 /* for convenience */
911 #define DUK_XTAG_BOOLEAN_FALSE    0xfff50000UL
912 #define DUK_XTAG_BOOLEAN_TRUE     0xfff50001UL
913 
914 #define DUK_TVAL_IS_VALID_TAG(tv) \
915 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
916 
917 /* DUK_TVAL_UNUSED initializer for duk_tval_unused, works for any endianness. */
918 #define DUK_TVAL_UNUSED_INITIALIZER() \
919 	{ DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED, DUK_TAG_UNUSED }
920 
921 /* two casts to avoid gcc warning: "warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]" */
922 #if defined(DUK_USE_64BIT_OPS)
923 #if defined(DUK_USE_DOUBLE_ME)
924 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
925 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 16) | (((duk_uint64_t) (duk_uint32_t) (h)) << 32); \
926 	} while (0)
927 #else
928 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
929 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) (tag)) << 48) | ((duk_uint64_t) (duk_uint32_t) (h)); \
930 	} while (0)
931 #endif
932 #else  /* DUK_USE_64BIT_OPS */
933 #define DUK__TVAL_SET_TAGGEDPOINTER(tv,h,tag)  do { \
934 		duk_tval *duk__tv; \
935 		duk__tv = (tv); \
936 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) (tag)) << 16; \
937 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (h); \
938 	} while (0)
939 #endif  /* DUK_USE_64BIT_OPS */
940 
941 #if defined(DUK_USE_64BIT_OPS)
942 /* Double casting for pointer to avoid gcc warning (cast from pointer to integer of different size) */
943 #if defined(DUK_USE_DOUBLE_ME)
944 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
945 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 16) | \
946 		                              ((duk_uint64_t) (flags)) | \
947 		                              (((duk_uint64_t) (duk_uint32_t) (fp)) << 32); \
948 	} while (0)
949 #else
950 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
951 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_LIGHTFUNC) << 48) | \
952 		                              (((duk_uint64_t) (flags)) << 32) | \
953 		                              ((duk_uint64_t) (duk_uint32_t) (fp)); \
954 	} while (0)
955 #endif
956 #else  /* DUK_USE_64BIT_OPS */
957 #define DUK__TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
958 		duk_tval *duk__tv; \
959 		duk__tv = (tv); \
960 		duk__tv->ui[DUK_DBL_IDX_UI0] = (((duk_uint32_t) DUK_TAG_LIGHTFUNC) << 16) | ((duk_uint32_t) (flags)); \
961 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (fp); \
962 	} while (0)
963 #endif  /* DUK_USE_64BIT_OPS */
964 
965 #if defined(DUK_USE_FASTINT)
966 /* Note: masking is done for 'i' to deal with negative numbers correctly */
967 #if defined(DUK_USE_DOUBLE_ME)
968 #define DUK__TVAL_SET_I48(tv,i)  do { \
969 		duk_tval *duk__tv; \
970 		duk__tv = (tv); \
971 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16 | (((duk_uint32_t) ((i) >> 32)) & 0x0000ffffUL); \
972 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
973 	} while (0)
974 #define DUK__TVAL_SET_U32(tv,i)  do { \
975 		duk_tval *duk__tv; \
976 		duk__tv = (tv); \
977 		duk__tv->ui[DUK_DBL_IDX_UI0] = ((duk_uint32_t) DUK_TAG_FASTINT) << 16; \
978 		duk__tv->ui[DUK_DBL_IDX_UI1] = (duk_uint32_t) (i); \
979 	} while (0)
980 #else
981 #define DUK__TVAL_SET_I48(tv,i)  do { \
982 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (((duk_uint64_t) (i)) & DUK_U64_CONSTANT(0x0000ffffffffffff)); \
983 	} while (0)
984 #define DUK__TVAL_SET_U32(tv,i)  do { \
985 		(tv)->ull[DUK_DBL_IDX_ULL0] = (((duk_uint64_t) DUK_TAG_FASTINT) << 48) | (duk_uint64_t) (i); \
986 	} while (0)
987 #endif
988 
989 /* This needs to go through a cast because sign extension is needed. */
990 #define DUK__TVAL_SET_I32(tv,i)  do { \
991 		duk_int64_t duk__tmp = (duk_int64_t) (i); \
992 		DUK_TVAL_SET_I48((tv), duk__tmp); \
993 	} while (0)
994 
995 /* XXX: Clumsy sign extend and masking of 16 topmost bits. */
996 #if defined(DUK_USE_DOUBLE_ME)
997 #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)
998 #else
999 #define DUK__TVAL_GET_FASTINT(tv)      ((((duk_int64_t) (tv)->ull[DUK_DBL_IDX_ULL0]) << 16) >> 16)
1000 #endif
1001 #define DUK__TVAL_GET_FASTINT_U32(tv)  ((tv)->ui[DUK_DBL_IDX_UI1])
1002 #define DUK__TVAL_GET_FASTINT_I32(tv)  ((duk_int32_t) (tv)->ui[DUK_DBL_IDX_UI1])
1003 #endif  /* DUK_USE_FASTINT */
1004 
1005 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1006 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNDEFINED; \
1007 	} while (0)
1008 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1009 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_UNUSED; \
1010 	} while (0)
1011 #define DUK_TVAL_SET_NULL(tv)  do { \
1012 		(tv)->us[DUK_DBL_IDX_US0] = (duk_uint16_t) DUK_TAG_NULL; \
1013 	} while (0)
1014 
1015 #define DUK_TVAL_SET_BOOLEAN(tv,val)         DUK_DBLUNION_SET_HIGH32((tv), (((duk_uint32_t) DUK_TAG_BOOLEAN) << 16) | ((duk_uint32_t) (val)))
1016 
1017 #define DUK_TVAL_SET_NAN(tv)                 DUK_DBLUNION_SET_NAN_FULL((tv))
1018 
1019 /* Assumes that caller has normalized NaNs, otherwise trouble ahead. */
1020 #if defined(DUK_USE_FASTINT)
1021 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1022 		duk_double_t duk__dblval; \
1023 		duk__dblval = (d); \
1024 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1025 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1026 	} while (0)
1027 #define DUK_TVAL_SET_I48(tv,i)               DUK__TVAL_SET_I48((tv), (i))
1028 #define DUK_TVAL_SET_I32(tv,i)               DUK__TVAL_SET_I32((tv), (i))
1029 #define DUK_TVAL_SET_U32(tv,i)               DUK__TVAL_SET_U32((tv), (i))
1030 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)  duk_tval_set_number_chkfast_fast((tv), (d))
1031 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)  duk_tval_set_number_chkfast_slow((tv), (d))
1032 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1033 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1034 		duk_tval *duk__tv; \
1035 		duk_double_t duk__d; \
1036 		duk__tv = (tv); \
1037 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1038 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1039 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1040 		} \
1041 	} while (0)
1042 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1043 		duk_tval *duk__tv; \
1044 		duk_double_t duk__d; \
1045 		duk__tv = (tv); \
1046 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1047 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1048 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1049 		} \
1050 	} while (0)
1051 #else  /* DUK_USE_FASTINT */
1052 #define DUK_TVAL_SET_DOUBLE(tv,d)  do { \
1053 		duk_double_t duk__dblval; \
1054 		duk__dblval = (d); \
1055 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); \
1056 		DUK_DBLUNION_SET_DOUBLE((tv), duk__dblval); \
1057 	} while (0)
1058 #define DUK_TVAL_SET_I48(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))  /* XXX: fast int-to-double */
1059 #define DUK_TVAL_SET_I32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1060 #define DUK_TVAL_SET_U32(tv,i)               DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
1061 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1062 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d)    DUK_TVAL_SET_DOUBLE((tv), (d))
1063 #define DUK_TVAL_SET_NUMBER(tv,d)            DUK_TVAL_SET_DOUBLE((tv), (d))
1064 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1065 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1066 #endif  /* DUK_USE_FASTINT */
1067 
1068 #define DUK_TVAL_SET_FASTINT(tv,i)           DUK_TVAL_SET_I48((tv), (i))  /* alias */
1069 
1070 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  DUK__TVAL_SET_LIGHTFUNC((tv), (fp), (flags))
1071 #define DUK_TVAL_SET_STRING(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_STRING)
1072 #define DUK_TVAL_SET_OBJECT(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_OBJECT)
1073 #define DUK_TVAL_SET_BUFFER(tv,h)            DUK__TVAL_SET_TAGGEDPOINTER((tv), (h), DUK_TAG_BUFFER)
1074 #define DUK_TVAL_SET_POINTER(tv,p)           DUK__TVAL_SET_TAGGEDPOINTER((tv), (p), DUK_TAG_POINTER)
1075 
1076 #define DUK_TVAL_SET_TVAL(tv,x)              do { *(tv) = *(x); } while (0)
1077 
1078 /* getters */
1079 #define DUK_TVAL_GET_BOOLEAN(tv)             ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US1])
1080 #if defined(DUK_USE_FASTINT)
1081 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1082 #define DUK_TVAL_GET_FASTINT(tv)             DUK__TVAL_GET_FASTINT((tv))
1083 #define DUK_TVAL_GET_FASTINT_U32(tv)         DUK__TVAL_GET_FASTINT_U32((tv))
1084 #define DUK_TVAL_GET_FASTINT_I32(tv)         DUK__TVAL_GET_FASTINT_I32((tv))
1085 #define DUK_TVAL_GET_NUMBER(tv)              duk_tval_get_number_packed((tv))
1086 #else
1087 #define DUK_TVAL_GET_NUMBER(tv)              ((tv)->d)
1088 #define DUK_TVAL_GET_DOUBLE(tv)              ((tv)->d)
1089 #endif
1090 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1091 		(out_flags) = (tv)->ui[DUK_DBL_IDX_UI0] & 0xffffUL; \
1092 		(out_fp) = (duk_c_function) (tv)->ui[DUK_DBL_IDX_UI1]; \
1093 	} while (0)
1094 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv)   ((duk_c_function) ((tv)->ui[DUK_DBL_IDX_UI1]))
1095 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)     (((duk_small_uint_t) (tv)->ui[DUK_DBL_IDX_UI0]) & 0xffffUL)
1096 #define DUK_TVAL_GET_STRING(tv)              ((duk_hstring *) (tv)->vp[DUK_DBL_IDX_VP1])
1097 #define DUK_TVAL_GET_OBJECT(tv)              ((duk_hobject *) (tv)->vp[DUK_DBL_IDX_VP1])
1098 #define DUK_TVAL_GET_BUFFER(tv)              ((duk_hbuffer *) (tv)->vp[DUK_DBL_IDX_VP1])
1099 #define DUK_TVAL_GET_POINTER(tv)             ((void *) (tv)->vp[DUK_DBL_IDX_VP1])
1100 #define DUK_TVAL_GET_HEAPHDR(tv)             ((duk_heaphdr *) (tv)->vp[DUK_DBL_IDX_VP1])
1101 
1102 /* decoding */
1103 #define DUK_TVAL_GET_TAG(tv)                 ((duk_small_uint_t) (tv)->us[DUK_DBL_IDX_US0])
1104 
1105 #define DUK_TVAL_IS_UNDEFINED(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNDEFINED)
1106 #define DUK_TVAL_IS_UNUSED(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_UNUSED)
1107 #define DUK_TVAL_IS_NULL(tv)                 (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_NULL)
1108 #define DUK_TVAL_IS_BOOLEAN(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BOOLEAN)
1109 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)         ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_TRUE)
1110 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)        ((tv)->ui[DUK_DBL_IDX_UI0] == DUK_XTAG_BOOLEAN_FALSE)
1111 #define DUK_TVAL_IS_LIGHTFUNC(tv)            (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_LIGHTFUNC)
1112 #define DUK_TVAL_IS_STRING(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_STRING)
1113 #define DUK_TVAL_IS_OBJECT(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_OBJECT)
1114 #define DUK_TVAL_IS_BUFFER(tv)               (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_BUFFER)
1115 #define DUK_TVAL_IS_POINTER(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_POINTER)
1116 #if defined(DUK_USE_FASTINT)
1117 /* 0xfff0 is -Infinity */
1118 #define DUK_TVAL_IS_DOUBLE(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1119 #define DUK_TVAL_IS_FASTINT(tv)              (DUK_TVAL_GET_TAG((tv)) == DUK_TAG_FASTINT)
1120 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff1UL)
1121 #else
1122 #define DUK_TVAL_IS_NUMBER(tv)               (DUK_TVAL_GET_TAG((tv)) <= 0xfff0UL)
1123 #define DUK_TVAL_IS_DOUBLE(tv)               DUK_TVAL_IS_NUMBER((tv))
1124 #endif
1125 
1126 /* This is performance critical because it appears in every DECREF. */
1127 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)       (DUK_TVAL_GET_TAG((tv)) >= DUK_TAG_STRING)
1128 
1129 #if defined(DUK_USE_FASTINT)
1130 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_packed(duk_tval *tv);
1131 #endif
1132 
1133 #else  /* DUK_USE_PACKED_TVAL */
1134 /* ======================================================================== */
1135 
1136 /*
1137  *  Portable 12-byte representation
1138  */
1139 
1140 /* Note: not initializing all bytes is normally not an issue: Duktape won't
1141  * read or use the uninitialized bytes so valgrind won't issue warnings.
1142  * In some special cases a harmless valgrind warning may be issued though.
1143  * For example, the DumpHeap debugger command writes out a compiled function's
1144  * 'data' area as is, including any uninitialized bytes, which causes a
1145  * valgrind warning.
1146  */
1147 
1148 typedef struct duk_tval_struct duk_tval;
1149 
1150 struct duk_tval_struct {
1151 	duk_small_uint_t t;
1152 	duk_small_uint_t v_extra;
1153 	union {
1154 		duk_double_t d;
1155 		duk_small_int_t i;
1156 #if defined(DUK_USE_FASTINT)
1157 		duk_int64_t fi;  /* if present, forces 16-byte duk_tval */
1158 #endif
1159 		void *voidptr;
1160 		duk_hstring *hstring;
1161 		duk_hobject *hobject;
1162 		duk_hcompfunc *hcompfunc;
1163 		duk_hnatfunc *hnatfunc;
1164 		duk_hthread *hthread;
1165 		duk_hbuffer *hbuffer;
1166 		duk_heaphdr *heaphdr;
1167 		duk_c_function lightfunc;
1168 	} v;
1169 };
1170 
1171 typedef struct {
1172 	duk_small_uint_t t;
1173 	duk_small_uint_t v_extra;
1174 	/* The rest of the fields don't matter except for debug dumps and such
1175 	 * for which a partial initializer may trigger out-ot-bounds memory
1176 	 * reads.  Include a double field which is usually as large or larger
1177 	 * than pointers (not always however).
1178 	 */
1179 	duk_double_t d;
1180 } duk_tval_unused;
1181 
1182 #define DUK_TVAL_UNUSED_INITIALIZER() \
1183 	{ DUK_TAG_UNUSED, 0, 0.0 }
1184 
1185 #define DUK_TAG_MIN                   0
1186 #define DUK_TAG_NUMBER                0  /* DUK_TAG_NUMBER only defined for non-packed duk_tval */
1187 #if defined(DUK_USE_FASTINT)
1188 #define DUK_TAG_FASTINT               1
1189 #endif
1190 #define DUK_TAG_UNDEFINED             2
1191 #define DUK_TAG_NULL                  3
1192 #define DUK_TAG_BOOLEAN               4
1193 #define DUK_TAG_POINTER               5
1194 #define DUK_TAG_LIGHTFUNC             6
1195 #define DUK_TAG_UNUSED                7  /* marker; not actual tagged type */
1196 #define DUK_TAG_STRING                8  /* first heap allocated, match bit boundary */
1197 #define DUK_TAG_OBJECT                9
1198 #define DUK_TAG_BUFFER                10
1199 #define DUK_TAG_MAX                   10
1200 
1201 #define DUK_TVAL_IS_VALID_TAG(tv) \
1202 	(DUK_TVAL_GET_TAG((tv)) - DUK_TAG_MIN <= DUK_TAG_MAX - DUK_TAG_MIN)
1203 
1204 /* DUK_TAG_NUMBER is intentionally first, as it is the default clause in code
1205  * to support the 8-byte representation.  Further, it is a non-heap-allocated
1206  * type so it should come before DUK_TAG_STRING.  Finally, it should not break
1207  * the tag value ranges covered by case-clauses in a switch-case.
1208  */
1209 
1210 /* setters */
1211 #define DUK_TVAL_SET_UNDEFINED(tv)  do { \
1212 		duk_tval *duk__tv; \
1213 		duk__tv = (tv); \
1214 		duk__tv->t = DUK_TAG_UNDEFINED; \
1215 	} while (0)
1216 
1217 #define DUK_TVAL_SET_UNUSED(tv)  do { \
1218 		duk_tval *duk__tv; \
1219 		duk__tv = (tv); \
1220 		duk__tv->t = DUK_TAG_UNUSED; \
1221 	} while (0)
1222 
1223 #define DUK_TVAL_SET_NULL(tv)  do { \
1224 		duk_tval *duk__tv; \
1225 		duk__tv = (tv); \
1226 		duk__tv->t = DUK_TAG_NULL; \
1227 	} while (0)
1228 
1229 #define DUK_TVAL_SET_BOOLEAN(tv,val)  do { \
1230 		duk_tval *duk__tv; \
1231 		duk__tv = (tv); \
1232 		duk__tv->t = DUK_TAG_BOOLEAN; \
1233 		duk__tv->v.i = (duk_small_int_t) (val); \
1234 	} while (0)
1235 
1236 #if defined(DUK_USE_FASTINT)
1237 #define DUK_TVAL_SET_DOUBLE(tv,val)  do { \
1238 		duk_tval *duk__tv; \
1239 		duk_double_t duk__dblval; \
1240 		duk__dblval = (val); \
1241 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1242 		duk__tv = (tv); \
1243 		duk__tv->t = DUK_TAG_NUMBER; \
1244 		duk__tv->v.d = duk__dblval; \
1245 	} while (0)
1246 #define DUK_TVAL_SET_I48(tv,val)  do { \
1247 		duk_tval *duk__tv; \
1248 		duk__tv = (tv); \
1249 		duk__tv->t = DUK_TAG_FASTINT; \
1250 		duk__tv->v.fi = (val); \
1251 	} while (0)
1252 #define DUK_TVAL_SET_U32(tv,val)  do { \
1253 		duk_tval *duk__tv; \
1254 		duk__tv = (tv); \
1255 		duk__tv->t = DUK_TAG_FASTINT; \
1256 		duk__tv->v.fi = (duk_int64_t) (val); \
1257 	} while (0)
1258 #define DUK_TVAL_SET_I32(tv,val)  do { \
1259 		duk_tval *duk__tv; \
1260 		duk__tv = (tv); \
1261 		duk__tv->t = DUK_TAG_FASTINT; \
1262 		duk__tv->v.fi = (duk_int64_t) (val); \
1263 	} while (0)
1264 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1265 	duk_tval_set_number_chkfast_fast((tv), (d))
1266 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1267 	duk_tval_set_number_chkfast_slow((tv), (d))
1268 #define DUK_TVAL_SET_NUMBER(tv,val) \
1269 	DUK_TVAL_SET_DOUBLE((tv), (val))
1270 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { \
1271 		duk_tval *duk__tv; \
1272 		duk_double_t duk__d; \
1273 		duk__tv = (tv); \
1274 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1275 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1276 			DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
1277 		} \
1278 	} while (0)
1279 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { \
1280 		duk_tval *duk__tv; \
1281 		duk_double_t duk__d; \
1282 		duk__tv = (tv); \
1283 		if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
1284 			duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
1285 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
1286 		} \
1287 	} while (0)
1288 #else  /* DUK_USE_FASTINT */
1289 #define DUK_TVAL_SET_DOUBLE(tv,d) \
1290 	DUK_TVAL_SET_NUMBER((tv), (d))
1291 #define DUK_TVAL_SET_I48(tv,val) \
1292 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))  /* XXX: fast int-to-double */
1293 #define DUK_TVAL_SET_U32(tv,val) \
1294 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1295 #define DUK_TVAL_SET_I32(tv,val) \
1296 	DUK_TVAL_SET_NUMBER((tv), (duk_double_t) (val))
1297 #define DUK_TVAL_SET_NUMBER(tv,val)  do { \
1298 		duk_tval *duk__tv; \
1299 		duk_double_t duk__dblval; \
1300 		duk__dblval = (val); \
1301 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(duk__dblval); /* nop for unpacked duk_tval */ \
1302 		duk__tv = (tv); \
1303 		duk__tv->t = DUK_TAG_NUMBER; \
1304 		duk__tv->v.d = duk__dblval; \
1305 	} while (0)
1306 #define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
1307 	DUK_TVAL_SET_NUMBER((tv), (d))
1308 #define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
1309 	DUK_TVAL_SET_NUMBER((tv), (d))
1310 #define DUK_TVAL_CHKFAST_INPLACE_FAST(tv)  do { } while (0)
1311 #define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv)  do { } while (0)
1312 #endif  /* DUK_USE_FASTINT */
1313 
1314 #define DUK_TVAL_SET_FASTINT(tv,i) \
1315 	DUK_TVAL_SET_I48((tv), (i))  /* alias */
1316 
1317 #define DUK_TVAL_SET_POINTER(tv,hptr)  do { \
1318 		duk_tval *duk__tv; \
1319 		duk__tv = (tv); \
1320 		duk__tv->t = DUK_TAG_POINTER; \
1321 		duk__tv->v.voidptr = (hptr); \
1322 	} while (0)
1323 
1324 #define DUK_TVAL_SET_LIGHTFUNC(tv,fp,flags)  do { \
1325 		duk_tval *duk__tv; \
1326 		duk__tv = (tv); \
1327 		duk__tv->t = DUK_TAG_LIGHTFUNC; \
1328 		duk__tv->v_extra = (flags); \
1329 		duk__tv->v.lightfunc = (duk_c_function) (fp); \
1330 	} while (0)
1331 
1332 #define DUK_TVAL_SET_STRING(tv,hptr)  do { \
1333 		duk_tval *duk__tv; \
1334 		duk__tv = (tv); \
1335 		duk__tv->t = DUK_TAG_STRING; \
1336 		duk__tv->v.hstring = (hptr); \
1337 	} while (0)
1338 
1339 #define DUK_TVAL_SET_OBJECT(tv,hptr)  do { \
1340 		duk_tval *duk__tv; \
1341 		duk__tv = (tv); \
1342 		duk__tv->t = DUK_TAG_OBJECT; \
1343 		duk__tv->v.hobject = (hptr); \
1344 	} while (0)
1345 
1346 #define DUK_TVAL_SET_BUFFER(tv,hptr)  do { \
1347 		duk_tval *duk__tv; \
1348 		duk__tv = (tv); \
1349 		duk__tv->t = DUK_TAG_BUFFER; \
1350 		duk__tv->v.hbuffer = (hptr); \
1351 	} while (0)
1352 
1353 #define DUK_TVAL_SET_NAN(tv)  do { \
1354 		/* in non-packed representation we don't care about which NaN is used */ \
1355 		duk_tval *duk__tv; \
1356 		duk__tv = (tv); \
1357 		duk__tv->t = DUK_TAG_NUMBER; \
1358 		duk__tv->v.d = DUK_DOUBLE_NAN; \
1359 	} while (0)
1360 
1361 #define DUK_TVAL_SET_TVAL(tv,x)            do { *(tv) = *(x); } while (0)
1362 
1363 /* getters */
1364 #define DUK_TVAL_GET_BOOLEAN(tv)           ((duk_small_uint_t) (tv)->v.i)
1365 #if defined(DUK_USE_FASTINT)
1366 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1367 #define DUK_TVAL_GET_FASTINT(tv)           ((tv)->v.fi)
1368 #define DUK_TVAL_GET_FASTINT_U32(tv)       ((duk_uint32_t) ((tv)->v.fi))
1369 #define DUK_TVAL_GET_FASTINT_I32(tv)       ((duk_int32_t) ((tv)->v.fi))
1370 #if 0
1371 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1372                                                (duk_double_t) DUK_TVAL_GET_FASTINT((tv)) : \
1373                                                DUK_TVAL_GET_DOUBLE((tv)))
1374 #define DUK_TVAL_GET_NUMBER(tv)            duk_tval_get_number_unpacked((tv))
1375 #else
1376 /* This seems reasonable overall. */
1377 #define DUK_TVAL_GET_NUMBER(tv)            (DUK_TVAL_IS_FASTINT((tv)) ? \
1378                                                duk_tval_get_number_unpacked_fastint((tv)) : \
1379                                                DUK_TVAL_GET_DOUBLE((tv)))
1380 #endif
1381 #else
1382 #define DUK_TVAL_GET_NUMBER(tv)            ((tv)->v.d)
1383 #define DUK_TVAL_GET_DOUBLE(tv)            ((tv)->v.d)
1384 #endif  /* DUK_USE_FASTINT */
1385 #define DUK_TVAL_GET_POINTER(tv)           ((tv)->v.voidptr)
1386 #define DUK_TVAL_GET_LIGHTFUNC(tv,out_fp,out_flags)  do { \
1387 		(out_flags) = (duk_uint32_t) (tv)->v_extra; \
1388 		(out_fp) = (tv)->v.lightfunc; \
1389 	} while (0)
1390 #define DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv) ((tv)->v.lightfunc)
1391 #define DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv)   ((duk_small_uint_t) ((tv)->v_extra))
1392 #define DUK_TVAL_GET_STRING(tv)            ((tv)->v.hstring)
1393 #define DUK_TVAL_GET_OBJECT(tv)            ((tv)->v.hobject)
1394 #define DUK_TVAL_GET_BUFFER(tv)            ((tv)->v.hbuffer)
1395 #define DUK_TVAL_GET_HEAPHDR(tv)           ((tv)->v.heaphdr)
1396 
1397 /* decoding */
1398 #define DUK_TVAL_GET_TAG(tv)               ((tv)->t)
1399 #define DUK_TVAL_IS_UNDEFINED(tv)          ((tv)->t == DUK_TAG_UNDEFINED)
1400 #define DUK_TVAL_IS_UNUSED(tv)             ((tv)->t == DUK_TAG_UNUSED)
1401 #define DUK_TVAL_IS_NULL(tv)               ((tv)->t == DUK_TAG_NULL)
1402 #define DUK_TVAL_IS_BOOLEAN(tv)            ((tv)->t == DUK_TAG_BOOLEAN)
1403 #define DUK_TVAL_IS_BOOLEAN_TRUE(tv)       (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i != 0))
1404 #define DUK_TVAL_IS_BOOLEAN_FALSE(tv)      (((tv)->t == DUK_TAG_BOOLEAN) && ((tv)->v.i == 0))
1405 #if defined(DUK_USE_FASTINT)
1406 #define DUK_TVAL_IS_DOUBLE(tv)             ((tv)->t == DUK_TAG_NUMBER)
1407 #define DUK_TVAL_IS_FASTINT(tv)            ((tv)->t == DUK_TAG_FASTINT)
1408 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER || \
1409                                             (tv)->t == DUK_TAG_FASTINT)
1410 #else
1411 #define DUK_TVAL_IS_NUMBER(tv)             ((tv)->t == DUK_TAG_NUMBER)
1412 #define DUK_TVAL_IS_DOUBLE(tv)             DUK_TVAL_IS_NUMBER((tv))
1413 #endif  /* DUK_USE_FASTINT */
1414 #define DUK_TVAL_IS_POINTER(tv)            ((tv)->t == DUK_TAG_POINTER)
1415 #define DUK_TVAL_IS_LIGHTFUNC(tv)          ((tv)->t == DUK_TAG_LIGHTFUNC)
1416 #define DUK_TVAL_IS_STRING(tv)             ((tv)->t == DUK_TAG_STRING)
1417 #define DUK_TVAL_IS_OBJECT(tv)             ((tv)->t == DUK_TAG_OBJECT)
1418 #define DUK_TVAL_IS_BUFFER(tv)             ((tv)->t == DUK_TAG_BUFFER)
1419 
1420 /* This is performance critical because it's needed for every DECREF.
1421  * Take advantage of the fact that the first heap allocated tag is 8,
1422  * so that bit 3 is set for all heap allocated tags (and never set for
1423  * non-heap-allocated tags).
1424  */
1425 #if 0
1426 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t >= DUK_TAG_STRING)
1427 #endif
1428 #define DUK_TVAL_IS_HEAP_ALLOCATED(tv)     ((tv)->t & 0x08)
1429 
1430 #if defined(DUK_USE_FASTINT)
1431 #if 0
1432 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked(duk_tval *tv);
1433 #endif
1434 DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv);
1435 #endif
1436 
1437 #endif  /* DUK_USE_PACKED_TVAL */
1438 
1439 /*
1440  *  Convenience (independent of representation)
1441  */
1442 
1443 #define DUK_TVAL_SET_BOOLEAN_TRUE(tv)        DUK_TVAL_SET_BOOLEAN((tv), 1)
1444 #define DUK_TVAL_SET_BOOLEAN_FALSE(tv)       DUK_TVAL_SET_BOOLEAN((tv), 0)
1445 
1446 #define DUK_TVAL_STRING_IS_SYMBOL(tv) \
1447 	DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING((tv)))
1448 
1449 /* Lightfunc flags packing and unpacking. */
1450 /* Sign extend: 0x0000##00 -> 0x##000000 -> sign extend to 0xssssss##.
1451  * Avoid signed shifts due to portability limitations.
1452  */
1453 #define DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags) \
1454 	((duk_int32_t) (duk_int8_t) (((duk_uint16_t) (lf_flags)) >> 8))
1455 #define DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags) \
1456 	(((lf_flags) >> 4) & 0x0fU)
1457 #define DUK_LFUNC_FLAGS_GET_NARGS(lf_flags) \
1458 	((lf_flags) & 0x0fU)
1459 #define DUK_LFUNC_FLAGS_PACK(magic,length,nargs) \
1460 	((((duk_small_uint_t) (magic)) & 0xffU) << 8) | ((length) << 4) | (nargs)
1461 
1462 #define DUK_LFUNC_NARGS_VARARGS             0x0f   /* varargs marker */
1463 #define DUK_LFUNC_NARGS_MIN                 0x00
1464 #define DUK_LFUNC_NARGS_MAX                 0x0e   /* max, excl. varargs marker */
1465 #define DUK_LFUNC_LENGTH_MIN                0x00
1466 #define DUK_LFUNC_LENGTH_MAX                0x0f
1467 #define DUK_LFUNC_MAGIC_MIN                 (-0x80)
1468 #define DUK_LFUNC_MAGIC_MAX                 0x7f
1469 
1470 /* fastint constants etc */
1471 #if defined(DUK_USE_FASTINT)
1472 #define DUK_FASTINT_MIN           (DUK_I64_CONSTANT(-0x800000000000))
1473 #define DUK_FASTINT_MAX           (DUK_I64_CONSTANT(0x7fffffffffff))
1474 #define DUK_FASTINT_BITS          48
1475 
1476 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
1477 DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
1478 #endif
1479 
1480 #endif  /* DUK_TVAL_H_INCLUDED */
1481 /* #include duk_builtins.h */
1482 #line 1 "duk_builtins.h"
1483 /*
1484  *  Automatically generated by genbuiltins.py, do not edit!
1485  */
1486 
1487 #if !defined(DUK_BUILTINS_H_INCLUDED)
1488 #define DUK_BUILTINS_H_INCLUDED
1489 
1490 #if defined(DUK_USE_ROM_STRINGS)
1491 #error ROM support not enabled, rerun configure.py with --rom-support
1492 #else  /* DUK_USE_ROM_STRINGS */
1493 #define DUK_STRIDX_UC_UNDEFINED                                       0                              /* 'Undefined' */
1494 #define DUK_HEAP_STRING_UC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_UNDEFINED)
1495 #define DUK_HTHREAD_STRING_UC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_UNDEFINED)
1496 #define DUK_STRIDX_UC_NULL                                            1                              /* 'Null' */
1497 #define DUK_HEAP_STRING_UC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NULL)
1498 #define DUK_HTHREAD_STRING_UC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NULL)
1499 #define DUK_STRIDX_UC_SYMBOL                                          2                              /* 'Symbol' */
1500 #define DUK_HEAP_STRING_UC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_SYMBOL)
1501 #define DUK_HTHREAD_STRING_UC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_SYMBOL)
1502 #define DUK_STRIDX_UC_ARGUMENTS                                       3                              /* 'Arguments' */
1503 #define DUK_HEAP_STRING_UC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ARGUMENTS)
1504 #define DUK_HTHREAD_STRING_UC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ARGUMENTS)
1505 #define DUK_STRIDX_UC_OBJECT                                          4                              /* 'Object' */
1506 #define DUK_HEAP_STRING_UC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_OBJECT)
1507 #define DUK_HTHREAD_STRING_UC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_OBJECT)
1508 #define DUK_STRIDX_UC_FUNCTION                                        5                              /* 'Function' */
1509 #define DUK_HEAP_STRING_UC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_FUNCTION)
1510 #define DUK_HTHREAD_STRING_UC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_FUNCTION)
1511 #define DUK_STRIDX_ARRAY                                              6                              /* 'Array' */
1512 #define DUK_HEAP_STRING_ARRAY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY)
1513 #define DUK_HTHREAD_STRING_ARRAY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY)
1514 #define DUK_STRIDX_UC_STRING                                          7                              /* 'String' */
1515 #define DUK_HEAP_STRING_UC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_STRING)
1516 #define DUK_HTHREAD_STRING_UC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_STRING)
1517 #define DUK_STRIDX_UC_BOOLEAN                                         8                              /* 'Boolean' */
1518 #define DUK_HEAP_STRING_UC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BOOLEAN)
1519 #define DUK_HTHREAD_STRING_UC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BOOLEAN)
1520 #define DUK_STRIDX_UC_NUMBER                                          9                              /* 'Number' */
1521 #define DUK_HEAP_STRING_UC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_NUMBER)
1522 #define DUK_HTHREAD_STRING_UC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_NUMBER)
1523 #define DUK_STRIDX_DATE                                               10                             /* 'Date' */
1524 #define DUK_HEAP_STRING_DATE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATE)
1525 #define DUK_HTHREAD_STRING_DATE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATE)
1526 #define DUK_STRIDX_REG_EXP                                            11                             /* 'RegExp' */
1527 #define DUK_HEAP_STRING_REG_EXP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_REG_EXP)
1528 #define DUK_HTHREAD_STRING_REG_EXP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_REG_EXP)
1529 #define DUK_STRIDX_UC_ERROR                                           12                             /* 'Error' */
1530 #define DUK_HEAP_STRING_UC_ERROR(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_ERROR)
1531 #define DUK_HTHREAD_STRING_UC_ERROR(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_ERROR)
1532 #define DUK_STRIDX_MATH                                               13                             /* 'Math' */
1533 #define DUK_HEAP_STRING_MATH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MATH)
1534 #define DUK_HTHREAD_STRING_MATH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MATH)
1535 #define DUK_STRIDX_JSON                                               14                             /* 'JSON' */
1536 #define DUK_HEAP_STRING_JSON(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON)
1537 #define DUK_HTHREAD_STRING_JSON(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON)
1538 #define DUK_STRIDX_EMPTY_STRING                                       15                             /* '' */
1539 #define DUK_HEAP_STRING_EMPTY_STRING(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EMPTY_STRING)
1540 #define DUK_HTHREAD_STRING_EMPTY_STRING(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EMPTY_STRING)
1541 #define DUK_STRIDX_ARRAY_BUFFER                                       16                             /* 'ArrayBuffer' */
1542 #define DUK_HEAP_STRING_ARRAY_BUFFER(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ARRAY_BUFFER)
1543 #define DUK_HTHREAD_STRING_ARRAY_BUFFER(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ARRAY_BUFFER)
1544 #define DUK_STRIDX_DATA_VIEW                                          17                             /* 'DataView' */
1545 #define DUK_HEAP_STRING_DATA_VIEW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA_VIEW)
1546 #define DUK_HTHREAD_STRING_DATA_VIEW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA_VIEW)
1547 #define DUK_STRIDX_INT8_ARRAY                                         18                             /* 'Int8Array' */
1548 #define DUK_HEAP_STRING_INT8_ARRAY(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT8_ARRAY)
1549 #define DUK_HTHREAD_STRING_INT8_ARRAY(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT8_ARRAY)
1550 #define DUK_STRIDX_UINT8_ARRAY                                        19                             /* 'Uint8Array' */
1551 #define DUK_HEAP_STRING_UINT8_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_ARRAY)
1552 #define DUK_HTHREAD_STRING_UINT8_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_ARRAY)
1553 #define DUK_STRIDX_UINT8_CLAMPED_ARRAY                                20                             /* 'Uint8ClampedArray' */
1554 #define DUK_HEAP_STRING_UINT8_CLAMPED_ARRAY(heap)                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1555 #define DUK_HTHREAD_STRING_UINT8_CLAMPED_ARRAY(thr)                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT8_CLAMPED_ARRAY)
1556 #define DUK_STRIDX_INT16_ARRAY                                        21                             /* 'Int16Array' */
1557 #define DUK_HEAP_STRING_INT16_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT16_ARRAY)
1558 #define DUK_HTHREAD_STRING_INT16_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT16_ARRAY)
1559 #define DUK_STRIDX_UINT16_ARRAY                                       22                             /* 'Uint16Array' */
1560 #define DUK_HEAP_STRING_UINT16_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT16_ARRAY)
1561 #define DUK_HTHREAD_STRING_UINT16_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT16_ARRAY)
1562 #define DUK_STRIDX_INT32_ARRAY                                        23                             /* 'Int32Array' */
1563 #define DUK_HEAP_STRING_INT32_ARRAY(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT32_ARRAY)
1564 #define DUK_HTHREAD_STRING_INT32_ARRAY(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT32_ARRAY)
1565 #define DUK_STRIDX_UINT32_ARRAY                                       24                             /* 'Uint32Array' */
1566 #define DUK_HEAP_STRING_UINT32_ARRAY(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UINT32_ARRAY)
1567 #define DUK_HTHREAD_STRING_UINT32_ARRAY(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UINT32_ARRAY)
1568 #define DUK_STRIDX_FLOAT32_ARRAY                                      25                             /* 'Float32Array' */
1569 #define DUK_HEAP_STRING_FLOAT32_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT32_ARRAY)
1570 #define DUK_HTHREAD_STRING_FLOAT32_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT32_ARRAY)
1571 #define DUK_STRIDX_FLOAT64_ARRAY                                      26                             /* 'Float64Array' */
1572 #define DUK_HEAP_STRING_FLOAT64_ARRAY(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLOAT64_ARRAY)
1573 #define DUK_HTHREAD_STRING_FLOAT64_ARRAY(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLOAT64_ARRAY)
1574 #define DUK_STRIDX_GLOBAL                                             27                             /* 'global' */
1575 #define DUK_HEAP_STRING_GLOBAL(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GLOBAL)
1576 #define DUK_HTHREAD_STRING_GLOBAL(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GLOBAL)
1577 #define DUK_STRIDX_OBJ_ENV                                            28                             /* 'ObjEnv' */
1578 #define DUK_HEAP_STRING_OBJ_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OBJ_ENV)
1579 #define DUK_HTHREAD_STRING_OBJ_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OBJ_ENV)
1580 #define DUK_STRIDX_DEC_ENV                                            29                             /* 'DecEnv' */
1581 #define DUK_HEAP_STRING_DEC_ENV(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEC_ENV)
1582 #define DUK_HTHREAD_STRING_DEC_ENV(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEC_ENV)
1583 #define DUK_STRIDX_UC_BUFFER                                          30                             /* 'Buffer' */
1584 #define DUK_HEAP_STRING_UC_BUFFER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_BUFFER)
1585 #define DUK_HTHREAD_STRING_UC_BUFFER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_BUFFER)
1586 #define DUK_STRIDX_UC_POINTER                                         31                             /* 'Pointer' */
1587 #define DUK_HEAP_STRING_UC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_POINTER)
1588 #define DUK_HTHREAD_STRING_UC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_POINTER)
1589 #define DUK_STRIDX_UC_THREAD                                          32                             /* 'Thread' */
1590 #define DUK_HEAP_STRING_UC_THREAD(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_UC_THREAD)
1591 #define DUK_HTHREAD_STRING_UC_THREAD(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_UC_THREAD)
1592 #define DUK_STRIDX_EVAL                                               33                             /* 'eval' */
1593 #define DUK_HEAP_STRING_EVAL(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EVAL)
1594 #define DUK_HTHREAD_STRING_EVAL(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EVAL)
1595 #define DUK_STRIDX_VALUE                                              34                             /* 'value' */
1596 #define DUK_HEAP_STRING_VALUE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE)
1597 #define DUK_HTHREAD_STRING_VALUE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE)
1598 #define DUK_STRIDX_WRITABLE                                           35                             /* 'writable' */
1599 #define DUK_HEAP_STRING_WRITABLE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WRITABLE)
1600 #define DUK_HTHREAD_STRING_WRITABLE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WRITABLE)
1601 #define DUK_STRIDX_CONFIGURABLE                                       36                             /* 'configurable' */
1602 #define DUK_HEAP_STRING_CONFIGURABLE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONFIGURABLE)
1603 #define DUK_HTHREAD_STRING_CONFIGURABLE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONFIGURABLE)
1604 #define DUK_STRIDX_ENUMERABLE                                         37                             /* 'enumerable' */
1605 #define DUK_HEAP_STRING_ENUMERABLE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUMERABLE)
1606 #define DUK_HTHREAD_STRING_ENUMERABLE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUMERABLE)
1607 #define DUK_STRIDX_JOIN                                               38                             /* 'join' */
1608 #define DUK_HEAP_STRING_JOIN(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JOIN)
1609 #define DUK_HTHREAD_STRING_JOIN(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JOIN)
1610 #define DUK_STRIDX_TO_LOCALE_STRING                                   39                             /* 'toLocaleString' */
1611 #define DUK_HEAP_STRING_TO_LOCALE_STRING(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_LOCALE_STRING)
1612 #define DUK_HTHREAD_STRING_TO_LOCALE_STRING(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_LOCALE_STRING)
1613 #define DUK_STRIDX_VALUE_OF                                           40                             /* 'valueOf' */
1614 #define DUK_HEAP_STRING_VALUE_OF(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VALUE_OF)
1615 #define DUK_HTHREAD_STRING_VALUE_OF(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VALUE_OF)
1616 #define DUK_STRIDX_TO_UTC_STRING                                      41                             /* 'toUTCString' */
1617 #define DUK_HEAP_STRING_TO_UTC_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_UTC_STRING)
1618 #define DUK_HTHREAD_STRING_TO_UTC_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_UTC_STRING)
1619 #define DUK_STRIDX_TO_ISO_STRING                                      42                             /* 'toISOString' */
1620 #define DUK_HEAP_STRING_TO_ISO_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_ISO_STRING)
1621 #define DUK_HTHREAD_STRING_TO_ISO_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_ISO_STRING)
1622 #define DUK_STRIDX_TO_GMT_STRING                                      43                             /* 'toGMTString' */
1623 #define DUK_HEAP_STRING_TO_GMT_STRING(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_GMT_STRING)
1624 #define DUK_HTHREAD_STRING_TO_GMT_STRING(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_GMT_STRING)
1625 #define DUK_STRIDX_SOURCE                                             44                             /* 'source' */
1626 #define DUK_HEAP_STRING_SOURCE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SOURCE)
1627 #define DUK_HTHREAD_STRING_SOURCE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SOURCE)
1628 #define DUK_STRIDX_IGNORE_CASE                                        45                             /* 'ignoreCase' */
1629 #define DUK_HEAP_STRING_IGNORE_CASE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IGNORE_CASE)
1630 #define DUK_HTHREAD_STRING_IGNORE_CASE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IGNORE_CASE)
1631 #define DUK_STRIDX_MULTILINE                                          46                             /* 'multiline' */
1632 #define DUK_HEAP_STRING_MULTILINE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MULTILINE)
1633 #define DUK_HTHREAD_STRING_MULTILINE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MULTILINE)
1634 #define DUK_STRIDX_LAST_INDEX                                         47                             /* 'lastIndex' */
1635 #define DUK_HEAP_STRING_LAST_INDEX(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LAST_INDEX)
1636 #define DUK_HTHREAD_STRING_LAST_INDEX(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LAST_INDEX)
1637 #define DUK_STRIDX_FLAGS                                              48                             /* 'flags' */
1638 #define DUK_HEAP_STRING_FLAGS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FLAGS)
1639 #define DUK_HTHREAD_STRING_FLAGS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FLAGS)
1640 #define DUK_STRIDX_INDEX                                              49                             /* 'index' */
1641 #define DUK_HEAP_STRING_INDEX(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INDEX)
1642 #define DUK_HTHREAD_STRING_INDEX(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INDEX)
1643 #define DUK_STRIDX_PROTOTYPE                                          50                             /* 'prototype' */
1644 #define DUK_HEAP_STRING_PROTOTYPE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTOTYPE)
1645 #define DUK_HTHREAD_STRING_PROTOTYPE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTOTYPE)
1646 #define DUK_STRIDX_CONSTRUCTOR                                        51                             /* 'constructor' */
1647 #define DUK_HEAP_STRING_CONSTRUCTOR(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCTOR)
1648 #define DUK_HTHREAD_STRING_CONSTRUCTOR(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCTOR)
1649 #define DUK_STRIDX_MESSAGE                                            52                             /* 'message' */
1650 #define DUK_HEAP_STRING_MESSAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MESSAGE)
1651 #define DUK_HTHREAD_STRING_MESSAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MESSAGE)
1652 #define DUK_STRIDX_LC_BOOLEAN                                         53                             /* 'boolean' */
1653 #define DUK_HEAP_STRING_LC_BOOLEAN(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_BOOLEAN)
1654 #define DUK_HTHREAD_STRING_LC_BOOLEAN(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_BOOLEAN)
1655 #define DUK_STRIDX_LC_NUMBER                                          54                             /* 'number' */
1656 #define DUK_HEAP_STRING_LC_NUMBER(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NUMBER)
1657 #define DUK_HTHREAD_STRING_LC_NUMBER(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NUMBER)
1658 #define DUK_STRIDX_LC_STRING                                          55                             /* 'string' */
1659 #define DUK_HEAP_STRING_LC_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_STRING)
1660 #define DUK_HTHREAD_STRING_LC_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_STRING)
1661 #define DUK_STRIDX_LC_SYMBOL                                          56                             /* 'symbol' */
1662 #define DUK_HEAP_STRING_LC_SYMBOL(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_SYMBOL)
1663 #define DUK_HTHREAD_STRING_LC_SYMBOL(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_SYMBOL)
1664 #define DUK_STRIDX_LC_OBJECT                                          57                             /* 'object' */
1665 #define DUK_HEAP_STRING_LC_OBJECT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_OBJECT)
1666 #define DUK_HTHREAD_STRING_LC_OBJECT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_OBJECT)
1667 #define DUK_STRIDX_LC_UNDEFINED                                       58                             /* 'undefined' */
1668 #define DUK_HEAP_STRING_LC_UNDEFINED(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_UNDEFINED)
1669 #define DUK_HTHREAD_STRING_LC_UNDEFINED(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_UNDEFINED)
1670 #define DUK_STRIDX_NAN                                                59                             /* 'NaN' */
1671 #define DUK_HEAP_STRING_NAN(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAN)
1672 #define DUK_HTHREAD_STRING_NAN(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAN)
1673 #define DUK_STRIDX_INFINITY                                           60                             /* 'Infinity' */
1674 #define DUK_HEAP_STRING_INFINITY(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INFINITY)
1675 #define DUK_HTHREAD_STRING_INFINITY(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INFINITY)
1676 #define DUK_STRIDX_MINUS_INFINITY                                     61                             /* '-Infinity' */
1677 #define DUK_HEAP_STRING_MINUS_INFINITY(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_INFINITY)
1678 #define DUK_HTHREAD_STRING_MINUS_INFINITY(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_INFINITY)
1679 #define DUK_STRIDX_MINUS_ZERO                                         62                             /* '-0' */
1680 #define DUK_HEAP_STRING_MINUS_ZERO(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_MINUS_ZERO)
1681 #define DUK_HTHREAD_STRING_MINUS_ZERO(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_MINUS_ZERO)
1682 #define DUK_STRIDX_COMMA                                              63                             /* ',' */
1683 #define DUK_HEAP_STRING_COMMA(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMMA)
1684 #define DUK_HTHREAD_STRING_COMMA(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMMA)
1685 #define DUK_STRIDX_NEWLINE_4SPACE                                     64                             /* '\n    ' */
1686 #define DUK_HEAP_STRING_NEWLINE_4SPACE(heap)                          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEWLINE_4SPACE)
1687 #define DUK_HTHREAD_STRING_NEWLINE_4SPACE(thr)                        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEWLINE_4SPACE)
1688 #define DUK_STRIDX_BRACKETED_ELLIPSIS                                 65                             /* '[...]' */
1689 #define DUK_HEAP_STRING_BRACKETED_ELLIPSIS(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BRACKETED_ELLIPSIS)
1690 #define DUK_HTHREAD_STRING_BRACKETED_ELLIPSIS(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BRACKETED_ELLIPSIS)
1691 #define DUK_STRIDX_INVALID_DATE                                       66                             /* 'Invalid Date' */
1692 #define DUK_HEAP_STRING_INVALID_DATE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INVALID_DATE)
1693 #define DUK_HTHREAD_STRING_INVALID_DATE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INVALID_DATE)
1694 #define DUK_STRIDX_LC_ARGUMENTS                                       67                             /* 'arguments' */
1695 #define DUK_HEAP_STRING_LC_ARGUMENTS(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_ARGUMENTS)
1696 #define DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_ARGUMENTS)
1697 #define DUK_STRIDX_CALLEE                                             68                             /* 'callee' */
1698 #define DUK_HEAP_STRING_CALLEE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLEE)
1699 #define DUK_HTHREAD_STRING_CALLEE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLEE)
1700 #define DUK_STRIDX_CALLER                                             69                             /* 'caller' */
1701 #define DUK_HEAP_STRING_CALLER(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CALLER)
1702 #define DUK_HTHREAD_STRING_CALLER(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CALLER)
1703 #define DUK_STRIDX_APPLY                                              70                             /* 'apply' */
1704 #define DUK_HEAP_STRING_APPLY(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_APPLY)
1705 #define DUK_HTHREAD_STRING_APPLY(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_APPLY)
1706 #define DUK_STRIDX_CONSTRUCT                                          71                             /* 'construct' */
1707 #define DUK_HEAP_STRING_CONSTRUCT(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONSTRUCT)
1708 #define DUK_HTHREAD_STRING_CONSTRUCT(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONSTRUCT)
1709 #define DUK_STRIDX_DELETE_PROPERTY                                    72                             /* 'deleteProperty' */
1710 #define DUK_HEAP_STRING_DELETE_PROPERTY(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE_PROPERTY)
1711 #define DUK_HTHREAD_STRING_DELETE_PROPERTY(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE_PROPERTY)
1712 #define DUK_STRIDX_GET                                                73                             /* 'get' */
1713 #define DUK_HEAP_STRING_GET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_GET)
1714 #define DUK_HTHREAD_STRING_GET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_GET)
1715 #define DUK_STRIDX_HAS                                                74                             /* 'has' */
1716 #define DUK_HEAP_STRING_HAS(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HAS)
1717 #define DUK_HTHREAD_STRING_HAS(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HAS)
1718 #define DUK_STRIDX_OWN_KEYS                                           75                             /* 'ownKeys' */
1719 #define DUK_HEAP_STRING_OWN_KEYS(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_OWN_KEYS)
1720 #define DUK_HTHREAD_STRING_OWN_KEYS(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_OWN_KEYS)
1721 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE                      76                             /* '\x81Symbol.toPrimitive\xff' */
1722 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1723 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_PRIMITIVE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)
1724 #define DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE                      77                             /* '\x81Symbol.hasInstance\xff' */
1725 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(heap)           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1726 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_HAS_INSTANCE(thr)         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)
1727 #define DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG                     78                             /* '\x81Symbol.toStringTag\xff' */
1728 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(heap)          DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1729 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_TO_STRING_TAG(thr)        DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG)
1730 #define DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE              79                             /* '\x81Symbol.isConcatSpreadable\xff' */
1731 #define DUK_HEAP_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(heap)   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1732 #define DUK_HTHREAD_STRING_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE(thr)  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE)
1733 #define DUK_STRIDX_SET_PROTOTYPE_OF                                   80                             /* 'setPrototypeOf' */
1734 #define DUK_HEAP_STRING_SET_PROTOTYPE_OF(heap)                        DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET_PROTOTYPE_OF)
1735 #define DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr)                      DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET_PROTOTYPE_OF)
1736 #define DUK_STRIDX___PROTO__                                          81                             /* '__proto__' */
1737 #define DUK_HEAP_STRING___PROTO__(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX___PROTO__)
1738 #define DUK_HTHREAD_STRING___PROTO__(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX___PROTO__)
1739 #define DUK_STRIDX_TO_STRING                                          82                             /* 'toString' */
1740 #define DUK_HEAP_STRING_TO_STRING(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_STRING)
1741 #define DUK_HTHREAD_STRING_TO_STRING(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_STRING)
1742 #define DUK_STRIDX_TO_JSON                                            83                             /* 'toJSON' */
1743 #define DUK_HEAP_STRING_TO_JSON(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TO_JSON)
1744 #define DUK_HTHREAD_STRING_TO_JSON(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TO_JSON)
1745 #define DUK_STRIDX_TYPE                                               84                             /* 'type' */
1746 #define DUK_HEAP_STRING_TYPE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPE)
1747 #define DUK_HTHREAD_STRING_TYPE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPE)
1748 #define DUK_STRIDX_DATA                                               85                             /* 'data' */
1749 #define DUK_HEAP_STRING_DATA(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DATA)
1750 #define DUK_HTHREAD_STRING_DATA(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DATA)
1751 #define DUK_STRIDX_LENGTH                                             86                             /* 'length' */
1752 #define DUK_HEAP_STRING_LENGTH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LENGTH)
1753 #define DUK_HTHREAD_STRING_LENGTH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LENGTH)
1754 #define DUK_STRIDX_SET                                                87                             /* 'set' */
1755 #define DUK_HEAP_STRING_SET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SET)
1756 #define DUK_HTHREAD_STRING_SET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SET)
1757 #define DUK_STRIDX_STACK                                              88                             /* 'stack' */
1758 #define DUK_HEAP_STRING_STACK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STACK)
1759 #define DUK_HTHREAD_STRING_STACK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STACK)
1760 #define DUK_STRIDX_PC                                                 89                             /* 'pc' */
1761 #define DUK_HEAP_STRING_PC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PC)
1762 #define DUK_HTHREAD_STRING_PC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PC)
1763 #define DUK_STRIDX_LINE_NUMBER                                        90                             /* 'lineNumber' */
1764 #define DUK_HEAP_STRING_LINE_NUMBER(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LINE_NUMBER)
1765 #define DUK_HTHREAD_STRING_LINE_NUMBER(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LINE_NUMBER)
1766 #define DUK_STRIDX_INT_TRACEDATA                                      91                             /* '\x82Tracedata' */
1767 #define DUK_HEAP_STRING_INT_TRACEDATA(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TRACEDATA)
1768 #define DUK_HTHREAD_STRING_INT_TRACEDATA(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TRACEDATA)
1769 #define DUK_STRIDX_NAME                                               92                             /* 'name' */
1770 #define DUK_HEAP_STRING_NAME(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NAME)
1771 #define DUK_HTHREAD_STRING_NAME(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NAME)
1772 #define DUK_STRIDX_FILE_NAME                                          93                             /* 'fileName' */
1773 #define DUK_HEAP_STRING_FILE_NAME(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FILE_NAME)
1774 #define DUK_HTHREAD_STRING_FILE_NAME(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FILE_NAME)
1775 #define DUK_STRIDX_LC_POINTER                                         94                             /* 'pointer' */
1776 #define DUK_HEAP_STRING_LC_POINTER(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_POINTER)
1777 #define DUK_HTHREAD_STRING_LC_POINTER(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_POINTER)
1778 #define DUK_STRIDX_INT_TARGET                                         95                             /* '\x82Target' */
1779 #define DUK_HEAP_STRING_INT_TARGET(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_TARGET)
1780 #define DUK_HTHREAD_STRING_INT_TARGET(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_TARGET)
1781 #define DUK_STRIDX_INT_NEXT                                           96                             /* '\x82Next' */
1782 #define DUK_HEAP_STRING_INT_NEXT(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_NEXT)
1783 #define DUK_HTHREAD_STRING_INT_NEXT(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_NEXT)
1784 #define DUK_STRIDX_INT_BYTECODE                                       97                             /* '\x82Bytecode' */
1785 #define DUK_HEAP_STRING_INT_BYTECODE(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_BYTECODE)
1786 #define DUK_HTHREAD_STRING_INT_BYTECODE(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_BYTECODE)
1787 #define DUK_STRIDX_INT_FORMALS                                        98                             /* '\x82Formals' */
1788 #define DUK_HEAP_STRING_INT_FORMALS(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FORMALS)
1789 #define DUK_HTHREAD_STRING_INT_FORMALS(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FORMALS)
1790 #define DUK_STRIDX_INT_VARMAP                                         99                             /* '\x82Varmap' */
1791 #define DUK_HEAP_STRING_INT_VARMAP(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARMAP)
1792 #define DUK_HTHREAD_STRING_INT_VARMAP(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARMAP)
1793 #define DUK_STRIDX_INT_SOURCE                                         100                            /* '\x82Source' */
1794 #define DUK_HEAP_STRING_INT_SOURCE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_SOURCE)
1795 #define DUK_HTHREAD_STRING_INT_SOURCE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_SOURCE)
1796 #define DUK_STRIDX_INT_PC2LINE                                        101                            /* '\x82Pc2line' */
1797 #define DUK_HEAP_STRING_INT_PC2LINE(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_PC2LINE)
1798 #define DUK_HTHREAD_STRING_INT_PC2LINE(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_PC2LINE)
1799 #define DUK_STRIDX_INT_MAP                                            102                            /* '\x82Map' */
1800 #define DUK_HEAP_STRING_INT_MAP(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_MAP)
1801 #define DUK_HTHREAD_STRING_INT_MAP(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_MAP)
1802 #define DUK_STRIDX_INT_VARENV                                         103                            /* '\x82Varenv' */
1803 #define DUK_HEAP_STRING_INT_VARENV(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VARENV)
1804 #define DUK_HTHREAD_STRING_INT_VARENV(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VARENV)
1805 #define DUK_STRIDX_INT_FINALIZER                                      104                            /* '\x82Finalizer' */
1806 #define DUK_HEAP_STRING_INT_FINALIZER(heap)                           DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_FINALIZER)
1807 #define DUK_HTHREAD_STRING_INT_FINALIZER(thr)                         DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_FINALIZER)
1808 #define DUK_STRIDX_INT_VALUE                                          105                            /* '\x82Value' */
1809 #define DUK_HEAP_STRING_INT_VALUE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INT_VALUE)
1810 #define DUK_HTHREAD_STRING_INT_VALUE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INT_VALUE)
1811 #define DUK_STRIDX_COMPILE                                            106                            /* 'compile' */
1812 #define DUK_HEAP_STRING_COMPILE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_COMPILE)
1813 #define DUK_HTHREAD_STRING_COMPILE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_COMPILE)
1814 #define DUK_STRIDX_INPUT                                              107                            /* 'input' */
1815 #define DUK_HEAP_STRING_INPUT(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INPUT)
1816 #define DUK_HTHREAD_STRING_INPUT(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INPUT)
1817 #define DUK_STRIDX_ERR_CREATE                                         108                            /* 'errCreate' */
1818 #define DUK_HEAP_STRING_ERR_CREATE(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_CREATE)
1819 #define DUK_HTHREAD_STRING_ERR_CREATE(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_CREATE)
1820 #define DUK_STRIDX_ERR_THROW                                          109                            /* 'errThrow' */
1821 #define DUK_HEAP_STRING_ERR_THROW(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ERR_THROW)
1822 #define DUK_HTHREAD_STRING_ERR_THROW(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ERR_THROW)
1823 #define DUK_STRIDX_ENV                                                110                            /* 'env' */
1824 #define DUK_HEAP_STRING_ENV(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENV)
1825 #define DUK_HTHREAD_STRING_ENV(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENV)
1826 #define DUK_STRIDX_HEX                                                111                            /* 'hex' */
1827 #define DUK_HEAP_STRING_HEX(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_HEX)
1828 #define DUK_HTHREAD_STRING_HEX(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_HEX)
1829 #define DUK_STRIDX_BASE64                                             112                            /* 'base64' */
1830 #define DUK_HEAP_STRING_BASE64(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BASE64)
1831 #define DUK_HTHREAD_STRING_BASE64(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BASE64)
1832 #define DUK_STRIDX_JX                                                 113                            /* 'jx' */
1833 #define DUK_HEAP_STRING_JX(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JX)
1834 #define DUK_HTHREAD_STRING_JX(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JX)
1835 #define DUK_STRIDX_JC                                                 114                            /* 'jc' */
1836 #define DUK_HEAP_STRING_JC(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JC)
1837 #define DUK_HTHREAD_STRING_JC(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JC)
1838 #define DUK_STRIDX_JSON_EXT_UNDEFINED                                 115                            /* '{"_undef":true}' */
1839 #define DUK_HEAP_STRING_JSON_EXT_UNDEFINED(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_UNDEFINED)
1840 #define DUK_HTHREAD_STRING_JSON_EXT_UNDEFINED(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_UNDEFINED)
1841 #define DUK_STRIDX_JSON_EXT_NAN                                       116                            /* '{"_nan":true}' */
1842 #define DUK_HEAP_STRING_JSON_EXT_NAN(heap)                            DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NAN)
1843 #define DUK_HTHREAD_STRING_JSON_EXT_NAN(thr)                          DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NAN)
1844 #define DUK_STRIDX_JSON_EXT_POSINF                                    117                            /* '{"_inf":true}' */
1845 #define DUK_HEAP_STRING_JSON_EXT_POSINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_POSINF)
1846 #define DUK_HTHREAD_STRING_JSON_EXT_POSINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_POSINF)
1847 #define DUK_STRIDX_JSON_EXT_NEGINF                                    118                            /* '{"_ninf":true}' */
1848 #define DUK_HEAP_STRING_JSON_EXT_NEGINF(heap)                         DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_NEGINF)
1849 #define DUK_HTHREAD_STRING_JSON_EXT_NEGINF(thr)                       DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_NEGINF)
1850 #define DUK_STRIDX_JSON_EXT_FUNCTION1                                 119                            /* '{"_func":true}' */
1851 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION1(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION1)
1852 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION1(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION1)
1853 #define DUK_STRIDX_JSON_EXT_FUNCTION2                                 120                            /* '{_func:true}' */
1854 #define DUK_HEAP_STRING_JSON_EXT_FUNCTION2(heap)                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_JSON_EXT_FUNCTION2)
1855 #define DUK_HTHREAD_STRING_JSON_EXT_FUNCTION2(thr)                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_JSON_EXT_FUNCTION2)
1856 #define DUK_STRIDX_BREAK                                              121                            /* 'break' */
1857 #define DUK_HEAP_STRING_BREAK(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_BREAK)
1858 #define DUK_HTHREAD_STRING_BREAK(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_BREAK)
1859 #define DUK_STRIDX_CASE                                               122                            /* 'case' */
1860 #define DUK_HEAP_STRING_CASE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CASE)
1861 #define DUK_HTHREAD_STRING_CASE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CASE)
1862 #define DUK_STRIDX_CATCH                                              123                            /* 'catch' */
1863 #define DUK_HEAP_STRING_CATCH(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CATCH)
1864 #define DUK_HTHREAD_STRING_CATCH(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CATCH)
1865 #define DUK_STRIDX_CONTINUE                                           124                            /* 'continue' */
1866 #define DUK_HEAP_STRING_CONTINUE(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONTINUE)
1867 #define DUK_HTHREAD_STRING_CONTINUE(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONTINUE)
1868 #define DUK_STRIDX_DEBUGGER                                           125                            /* 'debugger' */
1869 #define DUK_HEAP_STRING_DEBUGGER(heap)                                DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEBUGGER)
1870 #define DUK_HTHREAD_STRING_DEBUGGER(thr)                              DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEBUGGER)
1871 #define DUK_STRIDX_DEFAULT                                            126                            /* 'default' */
1872 #define DUK_HEAP_STRING_DEFAULT(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DEFAULT)
1873 #define DUK_HTHREAD_STRING_DEFAULT(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DEFAULT)
1874 #define DUK_STRIDX_DELETE                                             127                            /* 'delete' */
1875 #define DUK_HEAP_STRING_DELETE(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DELETE)
1876 #define DUK_HTHREAD_STRING_DELETE(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DELETE)
1877 #define DUK_STRIDX_DO                                                 128                            /* 'do' */
1878 #define DUK_HEAP_STRING_DO(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_DO)
1879 #define DUK_HTHREAD_STRING_DO(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_DO)
1880 #define DUK_STRIDX_ELSE                                               129                            /* 'else' */
1881 #define DUK_HEAP_STRING_ELSE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ELSE)
1882 #define DUK_HTHREAD_STRING_ELSE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ELSE)
1883 #define DUK_STRIDX_FINALLY                                            130                            /* 'finally' */
1884 #define DUK_HEAP_STRING_FINALLY(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FINALLY)
1885 #define DUK_HTHREAD_STRING_FINALLY(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FINALLY)
1886 #define DUK_STRIDX_FOR                                                131                            /* 'for' */
1887 #define DUK_HEAP_STRING_FOR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FOR)
1888 #define DUK_HTHREAD_STRING_FOR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FOR)
1889 #define DUK_STRIDX_LC_FUNCTION                                        132                            /* 'function' */
1890 #define DUK_HEAP_STRING_LC_FUNCTION(heap)                             DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_FUNCTION)
1891 #define DUK_HTHREAD_STRING_LC_FUNCTION(thr)                           DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_FUNCTION)
1892 #define DUK_STRIDX_IF                                                 133                            /* 'if' */
1893 #define DUK_HEAP_STRING_IF(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IF)
1894 #define DUK_HTHREAD_STRING_IF(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IF)
1895 #define DUK_STRIDX_IN                                                 134                            /* 'in' */
1896 #define DUK_HEAP_STRING_IN(heap)                                      DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IN)
1897 #define DUK_HTHREAD_STRING_IN(thr)                                    DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IN)
1898 #define DUK_STRIDX_INSTANCEOF                                         135                            /* 'instanceof' */
1899 #define DUK_HEAP_STRING_INSTANCEOF(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INSTANCEOF)
1900 #define DUK_HTHREAD_STRING_INSTANCEOF(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INSTANCEOF)
1901 #define DUK_STRIDX_NEW                                                136                            /* 'new' */
1902 #define DUK_HEAP_STRING_NEW(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_NEW)
1903 #define DUK_HTHREAD_STRING_NEW(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_NEW)
1904 #define DUK_STRIDX_RETURN                                             137                            /* 'return' */
1905 #define DUK_HEAP_STRING_RETURN(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_RETURN)
1906 #define DUK_HTHREAD_STRING_RETURN(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_RETURN)
1907 #define DUK_STRIDX_SWITCH                                             138                            /* 'switch' */
1908 #define DUK_HEAP_STRING_SWITCH(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SWITCH)
1909 #define DUK_HTHREAD_STRING_SWITCH(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SWITCH)
1910 #define DUK_STRIDX_THIS                                               139                            /* 'this' */
1911 #define DUK_HEAP_STRING_THIS(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THIS)
1912 #define DUK_HTHREAD_STRING_THIS(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THIS)
1913 #define DUK_STRIDX_THROW                                              140                            /* 'throw' */
1914 #define DUK_HEAP_STRING_THROW(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_THROW)
1915 #define DUK_HTHREAD_STRING_THROW(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_THROW)
1916 #define DUK_STRIDX_TRY                                                141                            /* 'try' */
1917 #define DUK_HEAP_STRING_TRY(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRY)
1918 #define DUK_HTHREAD_STRING_TRY(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRY)
1919 #define DUK_STRIDX_TYPEOF                                             142                            /* 'typeof' */
1920 #define DUK_HEAP_STRING_TYPEOF(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TYPEOF)
1921 #define DUK_HTHREAD_STRING_TYPEOF(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TYPEOF)
1922 #define DUK_STRIDX_VAR                                                143                            /* 'var' */
1923 #define DUK_HEAP_STRING_VAR(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VAR)
1924 #define DUK_HTHREAD_STRING_VAR(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VAR)
1925 #define DUK_STRIDX_CONST                                              144                            /* 'const' */
1926 #define DUK_HEAP_STRING_CONST(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CONST)
1927 #define DUK_HTHREAD_STRING_CONST(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CONST)
1928 #define DUK_STRIDX_VOID                                               145                            /* 'void' */
1929 #define DUK_HEAP_STRING_VOID(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_VOID)
1930 #define DUK_HTHREAD_STRING_VOID(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_VOID)
1931 #define DUK_STRIDX_WHILE                                              146                            /* 'while' */
1932 #define DUK_HEAP_STRING_WHILE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WHILE)
1933 #define DUK_HTHREAD_STRING_WHILE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WHILE)
1934 #define DUK_STRIDX_WITH                                               147                            /* 'with' */
1935 #define DUK_HEAP_STRING_WITH(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_WITH)
1936 #define DUK_HTHREAD_STRING_WITH(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_WITH)
1937 #define DUK_STRIDX_CLASS                                              148                            /* 'class' */
1938 #define DUK_HEAP_STRING_CLASS(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_CLASS)
1939 #define DUK_HTHREAD_STRING_CLASS(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_CLASS)
1940 #define DUK_STRIDX_ENUM                                               149                            /* 'enum' */
1941 #define DUK_HEAP_STRING_ENUM(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_ENUM)
1942 #define DUK_HTHREAD_STRING_ENUM(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_ENUM)
1943 #define DUK_STRIDX_EXPORT                                             150                            /* 'export' */
1944 #define DUK_HEAP_STRING_EXPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXPORT)
1945 #define DUK_HTHREAD_STRING_EXPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXPORT)
1946 #define DUK_STRIDX_EXTENDS                                            151                            /* 'extends' */
1947 #define DUK_HEAP_STRING_EXTENDS(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_EXTENDS)
1948 #define DUK_HTHREAD_STRING_EXTENDS(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_EXTENDS)
1949 #define DUK_STRIDX_IMPORT                                             152                            /* 'import' */
1950 #define DUK_HEAP_STRING_IMPORT(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPORT)
1951 #define DUK_HTHREAD_STRING_IMPORT(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPORT)
1952 #define DUK_STRIDX_SUPER                                              153                            /* 'super' */
1953 #define DUK_HEAP_STRING_SUPER(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_SUPER)
1954 #define DUK_HTHREAD_STRING_SUPER(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_SUPER)
1955 #define DUK_STRIDX_LC_NULL                                            154                            /* 'null' */
1956 #define DUK_HEAP_STRING_LC_NULL(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LC_NULL)
1957 #define DUK_HTHREAD_STRING_LC_NULL(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LC_NULL)
1958 #define DUK_STRIDX_TRUE                                               155                            /* 'true' */
1959 #define DUK_HEAP_STRING_TRUE(heap)                                    DUK_HEAP_GET_STRING((heap),DUK_STRIDX_TRUE)
1960 #define DUK_HTHREAD_STRING_TRUE(thr)                                  DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_TRUE)
1961 #define DUK_STRIDX_FALSE                                              156                            /* 'false' */
1962 #define DUK_HEAP_STRING_FALSE(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_FALSE)
1963 #define DUK_HTHREAD_STRING_FALSE(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_FALSE)
1964 #define DUK_STRIDX_IMPLEMENTS                                         157                            /* 'implements' */
1965 #define DUK_HEAP_STRING_IMPLEMENTS(heap)                              DUK_HEAP_GET_STRING((heap),DUK_STRIDX_IMPLEMENTS)
1966 #define DUK_HTHREAD_STRING_IMPLEMENTS(thr)                            DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_IMPLEMENTS)
1967 #define DUK_STRIDX_INTERFACE                                          158                            /* 'interface' */
1968 #define DUK_HEAP_STRING_INTERFACE(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_INTERFACE)
1969 #define DUK_HTHREAD_STRING_INTERFACE(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_INTERFACE)
1970 #define DUK_STRIDX_LET                                                159                            /* 'let' */
1971 #define DUK_HEAP_STRING_LET(heap)                                     DUK_HEAP_GET_STRING((heap),DUK_STRIDX_LET)
1972 #define DUK_HTHREAD_STRING_LET(thr)                                   DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_LET)
1973 #define DUK_STRIDX_PACKAGE                                            160                            /* 'package' */
1974 #define DUK_HEAP_STRING_PACKAGE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PACKAGE)
1975 #define DUK_HTHREAD_STRING_PACKAGE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PACKAGE)
1976 #define DUK_STRIDX_PRIVATE                                            161                            /* 'private' */
1977 #define DUK_HEAP_STRING_PRIVATE(heap)                                 DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PRIVATE)
1978 #define DUK_HTHREAD_STRING_PRIVATE(thr)                               DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PRIVATE)
1979 #define DUK_STRIDX_PROTECTED                                          162                            /* 'protected' */
1980 #define DUK_HEAP_STRING_PROTECTED(heap)                               DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PROTECTED)
1981 #define DUK_HTHREAD_STRING_PROTECTED(thr)                             DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PROTECTED)
1982 #define DUK_STRIDX_PUBLIC                                             163                            /* 'public' */
1983 #define DUK_HEAP_STRING_PUBLIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_PUBLIC)
1984 #define DUK_HTHREAD_STRING_PUBLIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_PUBLIC)
1985 #define DUK_STRIDX_STATIC                                             164                            /* 'static' */
1986 #define DUK_HEAP_STRING_STATIC(heap)                                  DUK_HEAP_GET_STRING((heap),DUK_STRIDX_STATIC)
1987 #define DUK_HTHREAD_STRING_STATIC(thr)                                DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_STATIC)
1988 #define DUK_STRIDX_YIELD                                              165                            /* 'yield' */
1989 #define DUK_HEAP_STRING_YIELD(heap)                                   DUK_HEAP_GET_STRING((heap),DUK_STRIDX_YIELD)
1990 #define DUK_HTHREAD_STRING_YIELD(thr)                                 DUK_HTHREAD_GET_STRING((thr),DUK_STRIDX_YIELD)
1991 
1992 #define DUK_HEAP_NUM_STRINGS                                          166
1993 #define DUK_STRIDX_START_RESERVED                                     121
1994 #define DUK_STRIDX_START_STRICT_RESERVED                              157
1995 #define DUK_STRIDX_END_RESERVED                                       166                            /* exclusive endpoint */
1996 
1997 /* To convert a heap stridx to a token number, subtract
1998  * DUK_STRIDX_START_RESERVED and add DUK_TOK_START_RESERVED.
1999  */
2000 #if !defined(DUK_SINGLE_FILE)
2001 DUK_INTERNAL_DECL const duk_uint8_t duk_strings_data[967];
2002 #endif  /* !DUK_SINGLE_FILE */
2003 #define DUK_STRDATA_MAX_STRLEN                                        27
2004 #define DUK_STRDATA_DATA_LENGTH                                       967
2005 #endif  /* DUK_USE_ROM_STRINGS */
2006 
2007 #if defined(DUK_USE_ROM_OBJECTS)
2008 #error RAM support not enabled, rerun configure.py with --ram-support
2009 #else  /* DUK_USE_ROM_OBJECTS */
2010 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor(duk_context *ctx);
2011 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_constructor(duk_context *ctx);
2012 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_context *ctx);
2013 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor(duk_context *ctx);
2014 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor(duk_context *ctx);
2015 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_constructor(duk_context *ctx);
2016 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_constructor(duk_context *ctx);
2017 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor(duk_context *ctx);
2018 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_constructor(duk_context *ctx);
2019 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_constructor_shared(duk_context *ctx);
2020 DUK_INTERNAL_DECL duk_ret_t duk_bi_type_error_thrower(duk_context *ctx);
2021 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_int(duk_context *ctx);
2022 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_parse_float(duk_context *ctx);
2023 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_constructor(duk_context *ctx);
2024 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_constructor(duk_context *ctx);
2025 DUK_INTERNAL_DECL duk_ret_t duk_bi_proxy_constructor(duk_context *ctx);
2026 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_constructor(duk_context *ctx);
2027 DUK_INTERNAL_DECL duk_ret_t duk_bi_dataview_constructor(duk_context *ctx);
2028 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_constructor(duk_context *ctx);
2029 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_context *ctx);
2030 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_constructor(duk_context *ctx);
2031 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_constructor(duk_context *ctx);
2032 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_eval(duk_context *ctx);
2033 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_nan(duk_context *ctx);
2034 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_is_finite(duk_context *ctx);
2035 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri(duk_context *ctx);
2036 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_decode_uri_component(duk_context *ctx);
2037 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri(duk_context *ctx);
2038 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_encode_uri_component(duk_context *ctx);
2039 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_escape(duk_context *ctx);
2040 DUK_INTERNAL_DECL duk_ret_t duk_bi_global_object_unescape(duk_context *ctx);
2041 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx);
2042 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx);
2043 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx);
2044 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx);
2045 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx);
2046 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx);
2047 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx);
2048 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx);
2049 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx);
2050 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx);
2051 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx);
2052 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx);
2053 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx);
2054 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx);
2055 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx);
2056 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx);
2057 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx);
2058 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx);
2059 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx);
2060 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_context *ctx);
2061 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_context *ctx);
2062 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_to_string(duk_context *ctx);
2063 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_apply(duk_context *ctx);
2064 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx);
2065 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx);
2066 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_length(duk_context *ctx);
2067 DUK_INTERNAL_DECL duk_ret_t duk_bi_native_function_name(duk_context *ctx);
2068 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_constructor_is_array(duk_context *ctx);
2069 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx);
2070 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_join_shared(duk_context *ctx);
2071 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx);
2072 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_pop(duk_context *ctx);
2073 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_push(duk_context *ctx);
2074 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reverse(duk_context *ctx);
2075 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_shift(duk_context *ctx);
2076 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_slice(duk_context *ctx);
2077 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_sort(duk_context *ctx);
2078 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_splice(duk_context *ctx);
2079 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_unshift(duk_context *ctx);
2080 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_context *ctx);
2081 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_iter_shared(duk_context *ctx);
2082 DUK_INTERNAL_DECL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_context *ctx);
2083 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_char_code(duk_context *ctx);
2084 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_constructor_from_code_point(duk_context *ctx);
2085 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_to_string(duk_context *ctx);
2086 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_at(duk_context *ctx);
2087 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_char_code_at(duk_context *ctx);
2088 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_concat(duk_context *ctx);
2089 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_context *ctx);
2090 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_locale_compare(duk_context *ctx);
2091 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_match(duk_context *ctx);
2092 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_replace(duk_context *ctx);
2093 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_search(duk_context *ctx);
2094 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_slice(duk_context *ctx);
2095 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_split(duk_context *ctx);
2096 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substring(duk_context *ctx);
2097 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_context *ctx);
2098 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_trim(duk_context *ctx);
2099 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx);
2100 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_context *ctx);
2101 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_includes(duk_context *ctx);
2102 DUK_INTERNAL_DECL duk_ret_t duk_bi_string_prototype_substr(duk_context *ctx);
2103 DUK_INTERNAL_DECL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_context *ctx);
2104 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_check_shared(duk_context *ctx);
2105 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_string(duk_context *ctx);
2106 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_context *ctx);
2107 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_value_of(duk_context *ctx);
2108 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_fixed(duk_context *ctx);
2109 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_exponential(duk_context *ctx);
2110 DUK_INTERNAL_DECL duk_ret_t duk_bi_number_prototype_to_precision(duk_context *ctx);
2111 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_parse(duk_context *ctx);
2112 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_utc(duk_context *ctx);
2113 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_constructor_now(duk_context *ctx);
2114 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_context *ctx);
2115 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_to_json(duk_context *ctx);
2116 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_value_of(duk_context *ctx);
2117 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_shared(duk_context *ctx);
2118 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_context *ctx);
2119 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_time(duk_context *ctx);
2120 DUK_INTERNAL_DECL duk_ret_t duk_bi_date_prototype_set_shared(duk_context *ctx);
2121 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_exec(duk_context *ctx);
2122 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_test(duk_context *ctx);
2123 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_tostring(duk_context *ctx);
2124 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_flags(duk_context *ctx);
2125 DUK_INTERNAL_DECL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_context *ctx);
2126 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_getter(duk_context *ctx);
2127 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_stack_setter(duk_context *ctx);
2128 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_getter(duk_context *ctx);
2129 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_filename_setter(duk_context *ctx);
2130 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_context *ctx);
2131 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_context *ctx);
2132 DUK_INTERNAL_DECL duk_ret_t duk_bi_error_prototype_to_string(duk_context *ctx);
2133 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_onearg_shared(duk_context *ctx);
2134 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_twoarg_shared(duk_context *ctx);
2135 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_clz32(duk_context *ctx);
2136 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_hypot(duk_context *ctx);
2137 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_imul(duk_context *ctx);
2138 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_max(duk_context *ctx);
2139 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_min(duk_context *ctx);
2140 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_random(duk_context *ctx);
2141 DUK_INTERNAL_DECL duk_ret_t duk_bi_math_object_sign(duk_context *ctx);
2142 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_parse(duk_context *ctx);
2143 DUK_INTERNAL_DECL duk_ret_t duk_bi_json_object_stringify(duk_context *ctx);
2144 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_info(duk_context *ctx);
2145 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_act(duk_context *ctx);
2146 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_gc(duk_context *ctx);
2147 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_fin(duk_context *ctx);
2148 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_enc(duk_context *ctx);
2149 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_dec(duk_context *ctx);
2150 DUK_INTERNAL_DECL duk_ret_t duk_bi_duktape_object_compact(duk_context *ctx);
2151 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_yield(duk_context *ctx);
2152 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_resume(duk_context *ctx);
2153 DUK_INTERNAL_DECL duk_ret_t duk_bi_thread_current(duk_context *ctx);
2154 DUK_INTERNAL_DECL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_context *ctx);
2155 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_apply(duk_context *ctx);
2156 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_construct(duk_context *ctx);
2157 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_delete_property(duk_context *ctx);
2158 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx);
2159 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_has(duk_context *ctx);
2160 DUK_INTERNAL_DECL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx);
2161 DUK_INTERNAL_DECL duk_ret_t duk_bi_arraybuffer_isview(duk_context *ctx);
2162 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_context *ctx);
2163 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_slice_shared(duk_context *ctx);
2164 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_context *ctx);
2165 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_buffer_getter(duk_context *ctx);
2166 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_readfield(duk_context *ctx);
2167 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_writefield(duk_context *ctx);
2168 DUK_INTERNAL_DECL duk_ret_t duk_bi_typedarray_set(duk_context *ctx);
2169 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_allocplain(duk_context *ctx);
2170 DUK_INTERNAL_DECL duk_ret_t duk_bi_uint8array_plainof(duk_context *ctx);
2171 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_concat(duk_context *ctx);
2172 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_context *ctx);
2173 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_context *ctx);
2174 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_context *ctx);
2175 DUK_INTERNAL_DECL duk_ret_t duk_bi_buffer_compare_shared(duk_context *ctx);
2176 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_context *ctx);
2177 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_context *ctx);
2178 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_fill(duk_context *ctx);
2179 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_copy(duk_context *ctx);
2180 DUK_INTERNAL_DECL duk_ret_t duk_bi_nodejs_buffer_write(duk_context *ctx);
2181 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_context *ctx);
2182 DUK_INTERNAL_DECL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx);
2183 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_context *ctx);
2184 DUK_INTERNAL_DECL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_context *ctx);
2185 DUK_INTERNAL_DECL duk_ret_t duk_bi_performance_now(duk_context *ctx);
2186 #if !defined(DUK_SINGLE_FILE)
2187 DUK_INTERNAL_DECL const duk_c_function duk_bi_native_functions[177];
2188 #endif  /* !DUK_SINGLE_FILE */
2189 #define DUK_BIDX_GLOBAL                                               0
2190 #define DUK_BIDX_GLOBAL_ENV                                           1
2191 #define DUK_BIDX_OBJECT_CONSTRUCTOR                                   2
2192 #define DUK_BIDX_OBJECT_PROTOTYPE                                     3
2193 #define DUK_BIDX_FUNCTION_CONSTRUCTOR                                 4
2194 #define DUK_BIDX_FUNCTION_PROTOTYPE                                   5
2195 #define DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE                            6
2196 #define DUK_BIDX_ARRAY_CONSTRUCTOR                                    7
2197 #define DUK_BIDX_ARRAY_PROTOTYPE                                      8
2198 #define DUK_BIDX_STRING_CONSTRUCTOR                                   9
2199 #define DUK_BIDX_STRING_PROTOTYPE                                     10
2200 #define DUK_BIDX_BOOLEAN_CONSTRUCTOR                                  11
2201 #define DUK_BIDX_BOOLEAN_PROTOTYPE                                    12
2202 #define DUK_BIDX_NUMBER_CONSTRUCTOR                                   13
2203 #define DUK_BIDX_NUMBER_PROTOTYPE                                     14
2204 #define DUK_BIDX_DATE_CONSTRUCTOR                                     15
2205 #define DUK_BIDX_DATE_PROTOTYPE                                       16
2206 #define DUK_BIDX_REGEXP_CONSTRUCTOR                                   17
2207 #define DUK_BIDX_REGEXP_PROTOTYPE                                     18
2208 #define DUK_BIDX_ERROR_CONSTRUCTOR                                    19
2209 #define DUK_BIDX_ERROR_PROTOTYPE                                      20
2210 #define DUK_BIDX_EVAL_ERROR_CONSTRUCTOR                               21
2211 #define DUK_BIDX_EVAL_ERROR_PROTOTYPE                                 22
2212 #define DUK_BIDX_RANGE_ERROR_CONSTRUCTOR                              23
2213 #define DUK_BIDX_RANGE_ERROR_PROTOTYPE                                24
2214 #define DUK_BIDX_REFERENCE_ERROR_CONSTRUCTOR                          25
2215 #define DUK_BIDX_REFERENCE_ERROR_PROTOTYPE                            26
2216 #define DUK_BIDX_SYNTAX_ERROR_CONSTRUCTOR                             27
2217 #define DUK_BIDX_SYNTAX_ERROR_PROTOTYPE                               28
2218 #define DUK_BIDX_TYPE_ERROR_CONSTRUCTOR                               29
2219 #define DUK_BIDX_TYPE_ERROR_PROTOTYPE                                 30
2220 #define DUK_BIDX_URI_ERROR_CONSTRUCTOR                                31
2221 #define DUK_BIDX_URI_ERROR_PROTOTYPE                                  32
2222 #define DUK_BIDX_TYPE_ERROR_THROWER                                   33
2223 #define DUK_BIDX_DUKTAPE                                              34
2224 #define DUK_BIDX_THREAD_PROTOTYPE                                     35
2225 #define DUK_BIDX_POINTER_PROTOTYPE                                    36
2226 #define DUK_BIDX_DOUBLE_ERROR                                         37
2227 #define DUK_BIDX_SYMBOL_PROTOTYPE                                     38
2228 #define DUK_BIDX_ARRAYBUFFER_PROTOTYPE                                39
2229 #define DUK_BIDX_DATAVIEW_PROTOTYPE                                   40
2230 #define DUK_BIDX_INT8ARRAY_PROTOTYPE                                  41
2231 #define DUK_BIDX_UINT8ARRAY_PROTOTYPE                                 42
2232 #define DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE                          43
2233 #define DUK_BIDX_INT16ARRAY_PROTOTYPE                                 44
2234 #define DUK_BIDX_UINT16ARRAY_PROTOTYPE                                45
2235 #define DUK_BIDX_INT32ARRAY_PROTOTYPE                                 46
2236 #define DUK_BIDX_UINT32ARRAY_PROTOTYPE                                47
2237 #define DUK_BIDX_FLOAT32ARRAY_PROTOTYPE                               48
2238 #define DUK_BIDX_FLOAT64ARRAY_PROTOTYPE                               49
2239 #define DUK_BIDX_NODEJS_BUFFER_PROTOTYPE                              50
2240 #define DUK_NUM_BUILTINS                                              51
2241 #define DUK_NUM_BIDX_BUILTINS                                         51
2242 #define DUK_NUM_ALL_BUILTINS                                          78
2243 #if defined(DUK_USE_DOUBLE_LE)
2244 #if !defined(DUK_SINGLE_FILE)
2245 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2246 #endif  /* !DUK_SINGLE_FILE */
2247 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2248 #elif defined(DUK_USE_DOUBLE_BE)
2249 #if !defined(DUK_SINGLE_FILE)
2250 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2251 #endif  /* !DUK_SINGLE_FILE */
2252 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2253 #elif defined(DUK_USE_DOUBLE_ME)
2254 #if !defined(DUK_SINGLE_FILE)
2255 DUK_INTERNAL_DECL const duk_uint8_t duk_builtins_data[4116];
2256 #endif  /* !DUK_SINGLE_FILE */
2257 #define DUK_BUILTINS_DATA_LENGTH                                      4116
2258 #else
2259 #error invalid endianness defines
2260 #endif
2261 #endif  /* DUK_USE_ROM_OBJECTS */
2262 #endif  /* DUK_BUILTINS_H_INCLUDED */
2263 #line 51 "duk_internal.h"
2264 
2265 /* #include duk_util.h */
2266 #line 1 "duk_util.h"
2267 /*
2268  *  Utilities
2269  */
2270 
2271 #if !defined(DUK_UTIL_H_INCLUDED)
2272 #define DUK_UTIL_H_INCLUDED
2273 
2274 #if defined(DUK_USE_GET_RANDOM_DOUBLE)
2275 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) DUK_USE_GET_RANDOM_DOUBLE((thr)->heap_udata)
2276 #else
2277 #define DUK_UTIL_GET_RANDOM_DOUBLE(thr) duk_util_tinyrandom_get_double(thr)
2278 #endif
2279 
2280 /*
2281  *  Some useful constants
2282  */
2283 
2284 #define DUK_DOUBLE_2TO32     4294967296.0
2285 #define DUK_DOUBLE_2TO31     2147483648.0
2286 #define DUK_DOUBLE_LOG2E     1.4426950408889634
2287 #define DUK_DOUBLE_LOG10E    0.4342944819032518
2288 
2289 /*
2290  *  Endian conversion
2291  */
2292 
2293 #if defined(DUK_USE_INTEGER_LE)
2294 #define DUK_HTON32(x) DUK_BSWAP32((x))
2295 #define DUK_NTOH32(x) DUK_BSWAP32((x))
2296 #define DUK_HTON16(x) DUK_BSWAP16((x))
2297 #define DUK_NTOH16(x) DUK_BSWAP16((x))
2298 #elif defined(DUK_USE_INTEGER_BE)
2299 #define DUK_HTON32(x) (x)
2300 #define DUK_NTOH32(x) (x)
2301 #define DUK_HTON16(x) (x)
2302 #define DUK_NTOH16(x) (x)
2303 #else
2304 #error internal error, endianness defines broken
2305 #endif
2306 
2307 /*
2308  *  Bitstream decoder
2309  */
2310 
2311 struct duk_bitdecoder_ctx {
2312 	const duk_uint8_t *data;
2313 	duk_size_t offset;
2314 	duk_size_t length;
2315 	duk_uint32_t currval;
2316 	duk_small_int_t currbits;
2317 };
2318 
2319 #define DUK_BD_BITPACKED_STRING_MAXLEN 256
2320 
2321 /*
2322  *  Bitstream encoder
2323  */
2324 
2325 struct duk_bitencoder_ctx {
2326 	duk_uint8_t *data;
2327 	duk_size_t offset;
2328 	duk_size_t length;
2329 	duk_uint32_t currval;
2330 	duk_small_int_t currbits;
2331 	duk_small_int_t truncated;
2332 };
2333 
2334 /*
2335  *  Raw write/read macros for big endian, unaligned basic values.
2336  *  Caller ensures there's enough space.  The macros update the pointer
2337  *  argument automatically on resizes.  The idiom seems a bit odd, but
2338  *  leads to compact code.
2339  */
2340 
2341 #define DUK_RAW_WRITE_U8(ptr,val)  do { \
2342 		*(ptr)++ = (duk_uint8_t) (val); \
2343 	} while (0)
2344 #define DUK_RAW_WRITE_U16_BE(ptr,val) duk_raw_write_u16_be(&(ptr), (duk_uint16_t) (val))
2345 #define DUK_RAW_WRITE_U32_BE(ptr,val) duk_raw_write_u32_be(&(ptr), (duk_uint32_t) (val))
2346 #define DUK_RAW_WRITE_DOUBLE_BE(ptr,val) duk_raw_write_double_be(&(ptr), (duk_double_t) (val))
2347 #define DUK_RAW_WRITE_XUTF8(ptr,val)  do { \
2348 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2349 		duk_uint8_t *duk__ptr; \
2350 		duk_small_int_t duk__len; \
2351 		duk__ptr = (duk_uint8_t *) (ptr); \
2352 		duk__len = duk_unicode_encode_xutf8((duk_ucodepoint_t) (val), duk__ptr); \
2353 		duk__ptr += duk__len; \
2354 		(ptr) = duk__ptr; \
2355 	} while (0)
2356 #define DUK_RAW_WRITE_CESU8(ptr,val)  do { \
2357 		/* 'ptr' is evaluated both as LHS and RHS. */ \
2358 		duk_uint8_t *duk__ptr; \
2359 		duk_small_int_t duk__len; \
2360 		duk__ptr = (duk_uint8_t *) (ptr); \
2361 		duk__len = duk_unicode_encode_cesu8((duk_ucodepoint_t) (val), duk__ptr); \
2362 		duk__ptr += duk__len; \
2363 		(ptr) = duk__ptr; \
2364 	} while (0)
2365 
2366 #define DUK_RAW_READ_U8(ptr) ((duk_uint8_t) (*(ptr)++))
2367 #define DUK_RAW_READ_U16_BE(ptr) duk_raw_read_u16_be(&(ptr));
2368 #define DUK_RAW_READ_U32_BE(ptr) duk_raw_read_u32_be(&(ptr));
2369 #define DUK_RAW_READ_DOUBLE_BE(ptr) duk_raw_read_double_be(&(ptr));
2370 
2371 /*
2372  *  Buffer writer (dynamic buffer only)
2373  *
2374  *  Helper for writing to a dynamic buffer with a concept of a "slack" area
2375  *  to reduce resizes.  You can ensure there is enough space beforehand and
2376  *  then write for a while without further checks, relying on a stable data
2377  *  pointer.  Slack handling is automatic so call sites only indicate how
2378  *  much data they need right now.
2379  *
2380  *  There are several ways to write using bufwriter.  The best approach
2381  *  depends mainly on how much performance matters over code footprint.
2382  *  The key issues are (1) ensuring there is space and (2) keeping the
2383  *  pointers consistent.  Fast code should ensure space for multiple writes
2384  *  with one ensure call.  Fastest inner loop code can temporarily borrow
2385  *  the 'p' pointer but must write it back eventually.
2386  *
2387  *  Be careful to ensure all macro arguments (other than static pointers like
2388  *  'thr' and 'bw_ctx') are evaluated exactly once, using temporaries if
2389  *  necessary (if that's not possible, there should be a note near the macro).
2390  *  Buffer write arguments often contain arithmetic etc so this is
2391  *  particularly important here.
2392  */
2393 
2394 /* XXX: Migrate bufwriter and other read/write helpers to its own header? */
2395 
2396 struct duk_bufwriter_ctx {
2397 	duk_uint8_t *p;
2398 	duk_uint8_t *p_base;
2399 	duk_uint8_t *p_limit;
2400 	duk_hbuffer_dynamic *buf;
2401 };
2402 
2403 #if defined(DUK_USE_PREFER_SIZE)
2404 #define DUK_BW_SLACK_ADD           64
2405 #define DUK_BW_SLACK_SHIFT         4    /* 2^4 -> 1/16 = 6.25% slack */
2406 #else
2407 #define DUK_BW_SLACK_ADD           64
2408 #define DUK_BW_SLACK_SHIFT         2    /* 2^2 -> 1/4 = 25% slack */
2409 #endif
2410 
2411 /* Initialization and finalization (compaction), converting to other types. */
2412 
2413 #define DUK_BW_INIT_PUSHBUF(thr,bw_ctx,sz) do { \
2414 		duk_bw_init_pushbuf((thr), (bw_ctx), (sz)); \
2415 	} while (0)
2416 #define DUK_BW_INIT_WITHBUF(thr,bw_ctx,buf) do { \
2417 		duk_bw_init((thr), (bw_ctx), (buf)); \
2418 	} while (0)
2419 #define DUK_BW_COMPACT(thr,bw_ctx) do { \
2420 		/* Make underlying buffer compact to match DUK_BW_GET_SIZE(). */ \
2421 		duk_bw_compact((thr), (bw_ctx)); \
2422 	} while (0)
2423 #define DUK_BW_PUSH_AS_STRING(thr,bw_ctx) do { \
2424 		duk_push_lstring((thr), \
2425 		                 (const char *) (bw_ctx)->p_base, \
2426 		                 (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2427 	} while (0)
2428 /* Pointers may be NULL for a while when 'buf' size is zero and before any
2429  * ENSURE calls have been made.  Once an ENSURE has been made, the pointers
2430  * are required to be non-NULL so that it's always valid to use memcpy() and
2431  * memmove(), even for zero size.
2432  */
2433 #define DUK_BW_ASSERT_VALID_EXPR(thr,bw_ctx) \
2434 	DUK_ASSERT_EXPR((bw_ctx) != NULL && \
2435 	                (bw_ctx)->buf != NULL && \
2436 			((DUK_HBUFFER_DYNAMIC_GET_SIZE((bw_ctx)->buf) == 0) || \
2437 				((bw_ctx)->p != NULL && \
2438 		                 (bw_ctx)->p_base != NULL && \
2439 		                 (bw_ctx)->p_limit != NULL && \
2440 		                 (bw_ctx)->p_limit >= (bw_ctx)->p_base && \
2441 		                 (bw_ctx)->p >= (bw_ctx)->p_base && \
2442 		                 (bw_ctx)->p <= (bw_ctx)->p_limit)))
2443 #define DUK_BW_ASSERT_VALID(thr,bw_ctx) do { \
2444 		DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)); \
2445 	} while (0)
2446 
2447 /* Working with the pointer and current size. */
2448 
2449 #define DUK_BW_GET_PTR(thr,bw_ctx) \
2450 	((bw_ctx)->p)
2451 #define DUK_BW_SET_PTR(thr,bw_ctx,ptr) do { \
2452 		(bw_ctx)->p = (ptr); \
2453 	} while (0)
2454 #define DUK_BW_ADD_PTR(thr,bw_ctx,delta) do { \
2455 		(bw_ctx)->p += (delta); \
2456 	} while (0)
2457 #define DUK_BW_GET_BASEPTR(thr,bw_ctx) \
2458 	((bw_ctx)->p_base)
2459 #define DUK_BW_GET_LIMITPTR(thr,bw_ctx) \
2460 	((bw_ctx)->p_limit)
2461 #define DUK_BW_GET_SIZE(thr,bw_ctx) \
2462 	((duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base))
2463 #define DUK_BW_SET_SIZE(thr,bw_ctx,sz) do { \
2464 		DUK_ASSERT((duk_size_t) (sz) <= (duk_size_t) ((bw_ctx)->p - (bw_ctx)->p_base)); \
2465 		(bw_ctx)->p = (bw_ctx)->p_base + (sz); \
2466 	} while (0)
2467 #define DUK_BW_RESET_SIZE(thr,bw_ctx) do { \
2468 		/* Reset to zero size, keep current limit. */ \
2469 		(bw_ctx)->p = (bw_ctx)->p_base; \
2470 	} while (0)
2471 #define DUK_BW_GET_BUFFER(thr,bw_ctx) \
2472 	((bw_ctx)->buf)
2473 
2474 /* Ensuring (reserving) space. */
2475 
2476 #define DUK_BW_ENSURE(thr,bw_ctx,sz) do { \
2477 		duk_size_t duk__sz, duk__space; \
2478 		DUK_BW_ASSERT_VALID((thr), (bw_ctx)); \
2479 		duk__sz = (sz); \
2480 		duk__space = (duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p); \
2481 		if (duk__space < duk__sz) { \
2482 			(void) duk_bw_resize((thr), (bw_ctx), duk__sz); \
2483 		} \
2484 	} while (0)
2485 /* NOTE: Multiple evaluation of 'ptr' in this macro. */
2486 /* XXX: Rework to use an always-inline function? */
2487 #define DUK_BW_ENSURE_RAW(thr,bw_ctx,sz,ptr) \
2488 	(((duk_size_t) ((bw_ctx)->p_limit - (ptr)) >= (sz)) ? \
2489 	 (ptr) : \
2490 	 ((bw_ctx)->p = (ptr), duk_bw_resize((thr),(bw_ctx),(sz))))
2491 #define DUK_BW_ENSURE_GETPTR(thr,bw_ctx,sz) \
2492 	DUK_BW_ENSURE_RAW((thr), (bw_ctx), (sz), (bw_ctx)->p)
2493 #define DUK_BW_ASSERT_SPACE_EXPR(thr,bw_ctx,sz) \
2494 	(DUK_BW_ASSERT_VALID_EXPR((thr), (bw_ctx)), \
2495 	 DUK_ASSERT_EXPR((duk_size_t) ((bw_ctx)->p_limit - (bw_ctx)->p) >= (duk_size_t) (sz)))
2496 #define DUK_BW_ASSERT_SPACE(thr,bw_ctx,sz) do { \
2497 		DUK_BW_ASSERT_SPACE_EXPR((thr), (bw_ctx), (sz)); \
2498 	} while (0)
2499 
2500 /* Miscellaneous. */
2501 
2502 #define DUK_BW_SETPTR_AND_COMPACT(thr,bw_ctx,ptr) do { \
2503 		(bw_ctx)->p = (ptr); \
2504 		duk_bw_compact((thr), (bw_ctx)); \
2505 	} while (0)
2506 
2507 /* Fast write calls which assume you control the slack beforehand.
2508  * Multibyte write variants exist and use a temporary write pointer
2509  * because byte writes alias with anything: with a stored pointer
2510  * explicit pointer load/stores get generated (e.g. gcc -Os).
2511  */
2512 
2513 #define DUK_BW_WRITE_RAW_U8(thr,bw_ctx,val) do { \
2514 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 1); \
2515 		*(bw_ctx)->p++ = (duk_uint8_t) (val); \
2516 	} while (0)
2517 #define DUK_BW_WRITE_RAW_U8_2(thr,bw_ctx,val1,val2) do { \
2518 		duk_uint8_t *duk__p; \
2519 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 2); \
2520 		duk__p = (bw_ctx)->p; \
2521 		*duk__p++ = (duk_uint8_t) (val1); \
2522 		*duk__p++ = (duk_uint8_t) (val2); \
2523 		(bw_ctx)->p = duk__p; \
2524 	} while (0)
2525 #define DUK_BW_WRITE_RAW_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2526 		duk_uint8_t *duk__p; \
2527 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 3); \
2528 		duk__p = (bw_ctx)->p; \
2529 		*duk__p++ = (duk_uint8_t) (val1); \
2530 		*duk__p++ = (duk_uint8_t) (val2); \
2531 		*duk__p++ = (duk_uint8_t) (val3); \
2532 		(bw_ctx)->p = duk__p; \
2533 	} while (0)
2534 #define DUK_BW_WRITE_RAW_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2535 		duk_uint8_t *duk__p; \
2536 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 4); \
2537 		duk__p = (bw_ctx)->p; \
2538 		*duk__p++ = (duk_uint8_t) (val1); \
2539 		*duk__p++ = (duk_uint8_t) (val2); \
2540 		*duk__p++ = (duk_uint8_t) (val3); \
2541 		*duk__p++ = (duk_uint8_t) (val4); \
2542 		(bw_ctx)->p = duk__p; \
2543 	} while (0)
2544 #define DUK_BW_WRITE_RAW_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2545 		duk_uint8_t *duk__p; \
2546 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 5); \
2547 		duk__p = (bw_ctx)->p; \
2548 		*duk__p++ = (duk_uint8_t) (val1); \
2549 		*duk__p++ = (duk_uint8_t) (val2); \
2550 		*duk__p++ = (duk_uint8_t) (val3); \
2551 		*duk__p++ = (duk_uint8_t) (val4); \
2552 		*duk__p++ = (duk_uint8_t) (val5); \
2553 		(bw_ctx)->p = duk__p; \
2554 	} while (0)
2555 #define DUK_BW_WRITE_RAW_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2556 		duk_uint8_t *duk__p; \
2557 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), 6); \
2558 		duk__p = (bw_ctx)->p; \
2559 		*duk__p++ = (duk_uint8_t) (val1); \
2560 		*duk__p++ = (duk_uint8_t) (val2); \
2561 		*duk__p++ = (duk_uint8_t) (val3); \
2562 		*duk__p++ = (duk_uint8_t) (val4); \
2563 		*duk__p++ = (duk_uint8_t) (val5); \
2564 		*duk__p++ = (duk_uint8_t) (val6); \
2565 		(bw_ctx)->p = duk__p; \
2566 	} while (0)
2567 #define DUK_BW_WRITE_RAW_XUTF8(thr,bw_ctx,cp) do { \
2568 		duk_ucodepoint_t duk__cp; \
2569 		duk_small_int_t duk__enc_len; \
2570 		duk__cp = (duk_ucodepoint_t) (cp); \
2571 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_xutf8_length(duk__cp)); \
2572 		duk__enc_len = duk_unicode_encode_xutf8(duk__cp, (bw_ctx)->p); \
2573 		(bw_ctx)->p += duk__enc_len; \
2574 	} while (0)
2575 #define DUK_BW_WRITE_RAW_CESU8(thr,bw_ctx,cp) do { \
2576 		duk_ucodepoint_t duk__cp; \
2577 		duk_small_int_t duk__enc_len; \
2578 		duk__cp = (duk_ucodepoint_t) (cp); \
2579 		DUK_BW_ASSERT_SPACE((thr), (bw_ctx), duk_unicode_get_cesu8_length(duk__cp)); \
2580 		duk__enc_len = duk_unicode_encode_cesu8(duk__cp, (bw_ctx)->p); \
2581 		(bw_ctx)->p += duk__enc_len; \
2582 	} while (0)
2583 /* XXX: add temporary duk__p pointer here too; sharing */
2584 /* XXX: avoid unsafe variants */
2585 #define DUK_BW_WRITE_RAW_BYTES(thr,bw_ctx,valptr,valsz) do { \
2586 		const void *duk__valptr; \
2587 		duk_size_t duk__valsz; \
2588 		duk__valptr = (const void *) (valptr); \
2589 		duk__valsz = (duk_size_t) (valsz); \
2590 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2591 		(bw_ctx)->p += duk__valsz; \
2592 	} while (0)
2593 #define DUK_BW_WRITE_RAW_CSTRING(thr,bw_ctx,val) do { \
2594 		const duk_uint8_t *duk__val; \
2595 		duk_size_t duk__val_len; \
2596 		duk__val = (const duk_uint8_t *) (val); \
2597 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2598 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2599 		(bw_ctx)->p += duk__val_len; \
2600 	} while (0)
2601 #define DUK_BW_WRITE_RAW_HSTRING(thr,bw_ctx,val) do { \
2602 		duk_size_t duk__val_len; \
2603 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2604 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2605 		(bw_ctx)->p += duk__val_len; \
2606 	} while (0)
2607 #define DUK_BW_WRITE_RAW_HBUFFER(thr,bw_ctx,val) do { \
2608 		duk_size_t duk__val_len; \
2609 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2610 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2611 		(bw_ctx)->p += duk__val_len; \
2612 	} while (0)
2613 #define DUK_BW_WRITE_RAW_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2614 		duk_size_t duk__val_len; \
2615 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2616 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2617 		(bw_ctx)->p += duk__val_len; \
2618 	} while (0)
2619 #define DUK_BW_WRITE_RAW_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2620 		duk_size_t duk__val_len; \
2621 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2622 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2623 		(bw_ctx)->p += duk__val_len; \
2624 	} while (0)
2625 
2626 /* Append bytes from a slice already in the buffer. */
2627 #define DUK_BW_WRITE_RAW_SLICE(thr,bw,dst_off,dst_len) \
2628 	duk_bw_write_raw_slice((thr), (bw), (dst_off), (dst_len))
2629 
2630 /* Insert bytes in the middle of the buffer from an external buffer. */
2631 #define DUK_BW_INSERT_RAW_BYTES(thr,bw,dst_off,buf,len) \
2632 	duk_bw_insert_raw_bytes((thr), (bw), (dst_off), (buf), (len))
2633 
2634 /* Insert bytes in the middle of the buffer from a slice already
2635  * in the buffer.  Source offset is interpreted "before" the operation.
2636  */
2637 #define DUK_BW_INSERT_RAW_SLICE(thr,bw,dst_off,src_off,len) \
2638 	duk_bw_insert_raw_slice((thr), (bw), (dst_off), (src_off), (len))
2639 
2640 /* Insert a reserved area somewhere in the buffer; caller fills it.
2641  * Evaluates to a (duk_uint_t *) pointing to the start of the reserved
2642  * area for convenience.
2643  */
2644 #define DUK_BW_INSERT_RAW_AREA(thr,bw,off,len) \
2645 	duk_bw_insert_raw_area((thr), (bw), (off), (len))
2646 
2647 /* Remove a slice from inside buffer. */
2648 #define DUK_BW_REMOVE_RAW_SLICE(thr,bw,off,len) \
2649 	duk_bw_remove_raw_slice((thr), (bw), (off), (len))
2650 
2651 /* Safe write calls which will ensure space first. */
2652 
2653 #define DUK_BW_WRITE_ENSURE_U8(thr,bw_ctx,val) do { \
2654 		DUK_BW_ENSURE((thr), (bw_ctx), 1); \
2655 		DUK_BW_WRITE_RAW_U8((thr), (bw_ctx), (val)); \
2656 	} while (0)
2657 #define DUK_BW_WRITE_ENSURE_U8_2(thr,bw_ctx,val1,val2) do { \
2658 		DUK_BW_ENSURE((thr), (bw_ctx), 2); \
2659 		DUK_BW_WRITE_RAW_U8_2((thr), (bw_ctx), (val1), (val2)); \
2660 	} while (0)
2661 #define DUK_BW_WRITE_ENSURE_U8_3(thr,bw_ctx,val1,val2,val3) do { \
2662 		DUK_BW_ENSURE((thr), (bw_ctx), 3); \
2663 		DUK_BW_WRITE_RAW_U8_3((thr), (bw_ctx), (val1), (val2), (val3)); \
2664 	} while (0)
2665 #define DUK_BW_WRITE_ENSURE_U8_4(thr,bw_ctx,val1,val2,val3,val4) do { \
2666 		DUK_BW_ENSURE((thr), (bw_ctx), 4); \
2667 		DUK_BW_WRITE_RAW_U8_4((thr), (bw_ctx), (val1), (val2), (val3), (val4)); \
2668 	} while (0)
2669 #define DUK_BW_WRITE_ENSURE_U8_5(thr,bw_ctx,val1,val2,val3,val4,val5) do { \
2670 		DUK_BW_ENSURE((thr), (bw_ctx), 5); \
2671 		DUK_BW_WRITE_RAW_U8_5((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5)); \
2672 	} while (0)
2673 #define DUK_BW_WRITE_ENSURE_U8_6(thr,bw_ctx,val1,val2,val3,val4,val5,val6) do { \
2674 		DUK_BW_ENSURE((thr), (bw_ctx), 6); \
2675 		DUK_BW_WRITE_RAW_U8_6((thr), (bw_ctx), (val1), (val2), (val3), (val4), (val5), (val6)); \
2676 	} while (0)
2677 #define DUK_BW_WRITE_ENSURE_XUTF8(thr,bw_ctx,cp) do { \
2678 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_XUTF8_LENGTH); \
2679 		DUK_BW_WRITE_RAW_XUTF8((thr), (bw_ctx), (cp)); \
2680 	} while (0)
2681 #define DUK_BW_WRITE_ENSURE_CESU8(thr,bw_ctx,cp) do { \
2682 		DUK_BW_ENSURE((thr), (bw_ctx), DUK_UNICODE_MAX_CESU8_LENGTH); \
2683 		DUK_BW_WRITE_RAW_CESU8((thr), (bw_ctx), (cp)); \
2684 	} while (0)
2685 /* XXX: add temporary duk__p pointer here too; sharing */
2686 /* XXX: avoid unsafe */
2687 #define DUK_BW_WRITE_ENSURE_BYTES(thr,bw_ctx,valptr,valsz) do { \
2688 		const void *duk__valptr; \
2689 		duk_size_t duk__valsz; \
2690 		duk__valptr = (const void *) (valptr); \
2691 		duk__valsz = (duk_size_t) (valsz); \
2692 		DUK_BW_ENSURE((thr), (bw_ctx), duk__valsz); \
2693 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), duk__valptr, duk__valsz); \
2694 		(bw_ctx)->p += duk__valsz; \
2695 	} while (0)
2696 #define DUK_BW_WRITE_ENSURE_CSTRING(thr,bw_ctx,val) do { \
2697 		const duk_uint8_t *duk__val; \
2698 		duk_size_t duk__val_len; \
2699 		duk__val = (const duk_uint8_t *) (val); \
2700 		duk__val_len = DUK_STRLEN((const char *) duk__val); \
2701 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2702 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) duk__val, duk__val_len); \
2703 		(bw_ctx)->p += duk__val_len; \
2704 	} while (0)
2705 #define DUK_BW_WRITE_ENSURE_HSTRING(thr,bw_ctx,val) do { \
2706 		duk_size_t duk__val_len; \
2707 		duk__val_len = DUK_HSTRING_GET_BYTELEN((val)); \
2708 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2709 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HSTRING_GET_DATA((val)), duk__val_len); \
2710 		(bw_ctx)->p += duk__val_len; \
2711 	} while (0)
2712 #define DUK_BW_WRITE_ENSURE_HBUFFER(thr,bw_ctx,val) do { \
2713 		duk_size_t duk__val_len; \
2714 		duk__val_len = DUK_HBUFFER_GET_SIZE((val)); \
2715 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2716 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2717 		(bw_ctx)->p += duk__val_len; \
2718 	} while (0)
2719 #define DUK_BW_WRITE_ENSURE_HBUFFER_FIXED(thr,bw_ctx,val) do { \
2720 		duk_size_t duk__val_len; \
2721 		duk__val_len = DUK_HBUFFER_FIXED_GET_SIZE((val)); \
2722 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2723 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_FIXED_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2724 		(bw_ctx)->p += duk__val_len; \
2725 	} while (0)
2726 #define DUK_BW_WRITE_ENSURE_HBUFFER_DYNAMIC(thr,bw_ctx,val) do { \
2727 		duk_size_t duk__val_len; \
2728 		duk__val_len = DUK_HBUFFER_DYNAMIC_GET_SIZE((val)); \
2729 		DUK_BW_ENSURE((thr), (bw_ctx), duk__val_len); \
2730 		duk_memcpy_unsafe((void *) ((bw_ctx)->p), (const void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((thr)->heap, (val)), duk__val_len); \
2731 		(bw_ctx)->p += duk__val_len; \
2732 	} while (0)
2733 
2734 #define DUK_BW_WRITE_ENSURE_SLICE(thr,bw,dst_off,dst_len) \
2735 	duk_bw_write_ensure_slice((thr), (bw), (dst_off), (dst_len))
2736 #define DUK_BW_INSERT_ENSURE_BYTES(thr,bw,dst_off,buf,len) \
2737 	duk_bw_insert_ensure_bytes((thr), (bw), (dst_off), (buf), (len))
2738 #define DUK_BW_INSERT_ENSURE_SLICE(thr,bw,dst_off,src_off,len) \
2739 	duk_bw_insert_ensure_slice((thr), (bw), (dst_off), (src_off), (len))
2740 #define DUK_BW_INSERT_ENSURE_AREA(thr,bw,off,len) \
2741 	/* Evaluates to (duk_uint8_t *) pointing to start of area. */ \
2742 	duk_bw_insert_ensure_area((thr), (bw), (off), (len))
2743 #define DUK_BW_REMOVE_ENSURE_SLICE(thr,bw,off,len) \
2744 	/* No difference between raw/ensure because the buffer shrinks. */ \
2745 	DUK_BW_REMOVE_RAW_SLICE((thr), (bw), (off), (len))
2746 
2747 /*
2748  *  Externs and prototypes
2749  */
2750 
2751 #if !defined(DUK_SINGLE_FILE)
2752 DUK_INTERNAL_DECL const duk_uint8_t duk_lc_digits[36];
2753 DUK_INTERNAL_DECL const duk_uint8_t duk_uc_nybbles[16];
2754 DUK_INTERNAL_DECL const duk_int8_t duk_hex_dectab[256];
2755 #if defined(DUK_USE_HEX_FASTPATH)
2756 DUK_INTERNAL_DECL const duk_int16_t duk_hex_dectab_shift4[256];
2757 DUK_INTERNAL_DECL const duk_uint16_t duk_hex_enctab[256];
2758 #endif
2759 #endif  /* !DUK_SINGLE_FILE */
2760 
2761 /* Note: assumes that duk_util_probe_steps size is 32 */
2762 #if defined(DUK_USE_HOBJECT_HASH_PART)
2763 #if !defined(DUK_SINGLE_FILE)
2764 DUK_INTERNAL_DECL duk_uint8_t duk_util_probe_steps[32];
2765 #endif  /* !DUK_SINGLE_FILE */
2766 #endif
2767 
2768 #if defined(DUK_USE_STRHASH_DENSE)
2769 DUK_INTERNAL_DECL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed);
2770 #endif
2771 
2772 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits);
2773 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx);
2774 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value);
2775 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);
2776 DUK_INTERNAL_DECL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx);
2777 DUK_INTERNAL_DECL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out);
2778 
2779 DUK_INTERNAL_DECL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits);
2780 DUK_INTERNAL_DECL void duk_be_finish(duk_bitencoder_ctx *ctx);
2781 
2782 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
2783 DUK_INTERNAL_DECL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr);
2784 DUK_INTERNAL_DECL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr);
2785 #endif
2786 
2787 DUK_INTERNAL_DECL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf);
2788 DUK_INTERNAL_DECL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size);
2789 DUK_INTERNAL_DECL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz);
2790 DUK_INTERNAL_DECL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx);
2791 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);
2792 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);
2793 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);
2794 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);
2795 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);
2796 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);
2797 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);
2798 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);
2799 DUK_INTERNAL_DECL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len);
2800 /* No duk_bw_remove_ensure_slice(), functionality would be identical. */
2801 
2802 DUK_INTERNAL_DECL duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p);
2803 DUK_INTERNAL_DECL duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p);
2804 DUK_INTERNAL_DECL duk_double_t duk_raw_read_double_be(duk_uint8_t **p);
2805 DUK_INTERNAL_DECL void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val);
2806 DUK_INTERNAL_DECL void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val);
2807 DUK_INTERNAL_DECL void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val);
2808 
2809 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* For now only needed by the debugger. */
2810 DUK_INTERNAL_DECL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len);
2811 #endif
2812 
2813 /* memcpy(), memmove() etc wrappers.  The plain variants like duk_memcpy()
2814  * assume C99+ and 'src' and 'dst' pointers must be non-NULL even when the
2815  * operation size is zero.  The unsafe variants like duk_memcpy_safe() deal
2816  * with the zero size case explicitly, and allow NULL pointers in that case
2817  * (which is undefined behavior in C99+).  For the majority of actual targets
2818  * a NULL pointer with a zero length is fine in practice.  These wrappers are
2819  * macros to force inlining; because there are hundreds of call sites, even a
2820  * few extra bytes per call site adds up to ~1kB footprint.
2821  */
2822 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
2823 #define duk_memcpy(dst,src,len)  do { \
2824 		void *duk__dst = (dst); \
2825 		const void *duk__src = (src); \
2826 		duk_size_t duk__len = (len); \
2827 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2828 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2829 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2830 	} while (0)
2831 #define duk_memcpy_unsafe(dst,src,len)  duk_memcpy((dst), (src), (len))
2832 #define duk_memmove(dst,src,len)  do { \
2833 		void *duk__dst = (dst); \
2834 		const void *duk__src = (src); \
2835 		duk_size_t duk__len = (len); \
2836 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2837 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2838 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2839 	} while (0)
2840 #define duk_memmove_unsafe(dst,src,len)  duk_memmove((dst), (src), (len))
2841 #define duk_memset(dst,val,len)  do { \
2842 		void *duk__dst = (dst); \
2843 		duk_small_int_t duk__val = (val); \
2844 		duk_size_t duk__len = (len); \
2845 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2846 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2847 	} while (0)
2848 #define duk_memset_unsafe(dst,val,len)  duk_memset((dst), (val), (len))
2849 #define duk_memzero(dst,len)  do { \
2850 		void *duk__dst = (dst); \
2851 		duk_size_t duk__len = (len); \
2852 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2853 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2854 	} while (0)
2855 #define duk_memzero_unsafe(dst,len)  duk_memzero((dst), (len))
2856 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2857 #define duk_memcpy(dst,src,len)  do { \
2858 		void *duk__dst = (dst); \
2859 		const void *duk__src = (src); \
2860 		duk_size_t duk__len = (len); \
2861 		DUK_ASSERT(duk__dst != NULL); \
2862 		DUK_ASSERT(duk__src != NULL); \
2863 		(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2864 	} while (0)
2865 #define duk_memcpy_unsafe(dst,src,len)  do { \
2866 		void *duk__dst = (dst); \
2867 		const void *duk__src = (src); \
2868 		duk_size_t duk__len = (len); \
2869 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2870 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2871 		if (DUK_LIKELY(duk__len > 0U)) { \
2872 			DUK_ASSERT(duk__dst != NULL); \
2873 			DUK_ASSERT(duk__src != NULL); \
2874 			(void) DUK_MEMCPY(duk__dst, duk__src, (size_t) duk__len); \
2875 		} \
2876 	} while (0)
2877 #define duk_memmove(dst,src,len)  do { \
2878 		void *duk__dst = (dst); \
2879 		const void *duk__src = (src); \
2880 		duk_size_t duk__len = (len); \
2881 		DUK_ASSERT(duk__dst != NULL); \
2882 		DUK_ASSERT(duk__src != NULL); \
2883 		(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2884 	} while (0)
2885 #define duk_memmove_unsafe(dst,src,len)  do { \
2886 		void *duk__dst = (dst); \
2887 		const void *duk__src = (src); \
2888 		duk_size_t duk__len = (len); \
2889 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2890 		DUK_ASSERT(duk__src != NULL || duk__len == 0U); \
2891 		if (DUK_LIKELY(duk__len > 0U)) { \
2892 			DUK_ASSERT(duk__dst != NULL); \
2893 			DUK_ASSERT(duk__src != NULL); \
2894 			(void) DUK_MEMMOVE(duk__dst, duk__src, (size_t) duk__len); \
2895 		} \
2896 	} while (0)
2897 #define duk_memset(dst,val,len)  do { \
2898 		void *duk__dst = (dst); \
2899 		duk_small_int_t duk__val = (val); \
2900 		duk_size_t duk__len = (len); \
2901 		DUK_ASSERT(duk__dst != NULL); \
2902 		(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2903 	} while (0)
2904 #define duk_memset_unsafe(dst,val,len)  do { \
2905 		void *duk__dst = (dst); \
2906 		duk_small_int_t duk__val = (val); \
2907 		duk_size_t duk__len = (len); \
2908 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2909 		if (DUK_LIKELY(duk__len > 0U)) { \
2910 			DUK_ASSERT(duk__dst != NULL); \
2911 			(void) DUK_MEMSET(duk__dst, duk__val, (size_t) duk__len); \
2912 		} \
2913 	} while (0)
2914 #define duk_memzero(dst,len)  do { \
2915 		void *duk__dst = (dst); \
2916 		duk_size_t duk__len = (len); \
2917 		DUK_ASSERT(duk__dst != NULL); \
2918 		(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2919 	} while (0)
2920 #define duk_memzero_unsafe(dst,len)  do { \
2921 		void *duk__dst = (dst); \
2922 		duk_size_t duk__len = (len); \
2923 		DUK_ASSERT(duk__dst != NULL || duk__len == 0U); \
2924 		if (DUK_LIKELY(duk__len > 0U)) { \
2925 			DUK_ASSERT(duk__dst != NULL); \
2926 			(void) DUK_MEMZERO(duk__dst, (size_t) duk__len); \
2927 		} \
2928 	} while (0)
2929 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
2930 
2931 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len);
2932 DUK_INTERNAL_DECL duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len);
2933 
2934 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival);
2935 DUK_INTERNAL_DECL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival);
2936 DUK_INTERNAL_DECL duk_bool_t duk_double_is_anyinf(duk_double_t x);
2937 DUK_INTERNAL_DECL duk_bool_t duk_double_is_posinf(duk_double_t x);
2938 DUK_INTERNAL_DECL duk_bool_t duk_double_is_neginf(duk_double_t x);
2939 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan(duk_double_t x);
2940 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x);
2941 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x);
2942 DUK_INTERNAL_DECL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x);
2943 DUK_INTERNAL_DECL duk_small_uint_t duk_double_signbit(duk_double_t x);
2944 DUK_INTERNAL_DECL duk_double_t duk_double_trunc_towards_zero(duk_double_t x);
2945 DUK_INTERNAL_DECL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y);
2946 DUK_INTERNAL_DECL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y);
2947 DUK_INTERNAL_DECL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y);
2948 DUK_INTERNAL_DECL duk_bool_t duk_double_is_finite(duk_double_t x);
2949 DUK_INTERNAL_DECL duk_bool_t duk_double_is_integer(duk_double_t x);
2950 DUK_INTERNAL_DECL duk_bool_t duk_double_is_safe_integer(duk_double_t x);
2951 
2952 DUK_INTERNAL_DECL duk_double_t duk_double_div(duk_double_t x, duk_double_t y);
2953 DUK_INTERNAL_DECL duk_int_t duk_double_to_int_t(duk_double_t x);
2954 DUK_INTERNAL_DECL duk_uint_t duk_double_to_uint_t(duk_double_t x);
2955 DUK_INTERNAL_DECL duk_int32_t duk_double_to_int32_t(duk_double_t x);
2956 DUK_INTERNAL_DECL duk_uint32_t duk_double_to_uint32_t(duk_double_t x);
2957 DUK_INTERNAL_DECL duk_float_t duk_double_to_float_t(duk_double_t x);
2958 
2959 /*
2960  *  Miscellaneous
2961  */
2962 
2963 /* Example: x     = 0x10 = 0b00010000
2964  *          x - 1 = 0x0f = 0b00001111
2965  *          x & (x - 1) == 0
2966  *
2967  *          x     = 0x07 = 0b00000111
2968  *          x - 1 = 0x06 = 0b00000110
2969  *          x & (x - 1) != 0
2970  *
2971  * However, incorrectly true for x == 0 so check for that explicitly.
2972  */
2973 #define DUK_IS_POWER_OF_TWO(x) \
2974 	((x) != 0U && ((x) & ((x) - 1U)) == 0U)
2975 
2976 #endif  /* DUK_UTIL_H_INCLUDED */
2977 /* #include duk_strings.h */
2978 #line 1 "duk_strings.h"
2979 /*
2980  *  Shared string macros.
2981  *
2982  *  Using shared macros helps minimize strings data size because it's easy
2983  *  to check if an existing string could be used.  String constants don't
2984  *  need to be all defined here; defining a string here makes sense if there's
2985  *  a high chance the string could be reused.  Also, using macros allows
2986  *  a call site express the exact string needed, but the macro may map to an
2987  *  approximate string to reduce unique string count.  Macros can also be
2988  *  more easily tuned for low memory targets than #if defined()s throughout
2989  *  the code base.
2990  *
2991  *  Because format strings behave differently in the call site (they need to
2992  *  be followed by format arguments), they use a special prefix DUK_STR_FMT_.
2993  *
2994  *  On some compilers using explicit shared strings is preferable; on others
2995  *  it may be better to use straight literals because the compiler will combine
2996  *  them anyway, and such strings won't end up unnecessarily in a symbol table.
2997  */
2998 
2999 #if !defined(DUK_ERRMSG_H_INCLUDED)
3000 #define DUK_ERRMSG_H_INCLUDED
3001 
3002 /* Mostly API and built-in method related */
3003 #define DUK_STR_INTERNAL_ERROR                   "internal error"
3004 #define DUK_STR_UNSUPPORTED                      "unsupported"
3005 #define DUK_STR_INVALID_COUNT                    "invalid count"
3006 #define DUK_STR_INVALID_ARGS                     "invalid args"
3007 #define DUK_STR_INVALID_STATE                    "invalid state"
3008 #define DUK_STR_INVALID_INPUT                    "invalid input"
3009 #define DUK_STR_INVALID_LENGTH                   "invalid length"
3010 #define DUK_STR_NOT_CONSTRUCTABLE                "not constructable"
3011 #define DUK_STR_CONSTRUCT_ONLY                   "constructor requires 'new'"
3012 #define DUK_STR_NOT_CALLABLE                     "not callable"
3013 #define DUK_STR_NOT_EXTENSIBLE                   "not extensible"
3014 #define DUK_STR_NOT_WRITABLE                     "not writable"
3015 #define DUK_STR_NOT_CONFIGURABLE                 "not configurable"
3016 #define DUK_STR_INVALID_CONTEXT                  "invalid context"
3017 #define DUK_STR_INVALID_INDEX                    "invalid args"
3018 #define DUK_STR_PUSH_BEYOND_ALLOC_STACK          "cannot push beyond allocated stack"
3019 #define DUK_STR_NOT_UNDEFINED                    "unexpected type"
3020 #define DUK_STR_NOT_NULL                         "unexpected type"
3021 #define DUK_STR_NOT_BOOLEAN                      "unexpected type"
3022 #define DUK_STR_NOT_NUMBER                       "unexpected type"
3023 #define DUK_STR_NOT_STRING                       "unexpected type"
3024 #define DUK_STR_NOT_OBJECT                       "unexpected type"
3025 #define DUK_STR_NOT_POINTER                      "unexpected type"
3026 #define DUK_STR_NOT_BUFFER                       "not buffer"  /* still in use with verbose messages */
3027 #define DUK_STR_UNEXPECTED_TYPE                  "unexpected type"
3028 #define DUK_STR_NOT_THREAD                       "unexpected type"
3029 #define DUK_STR_NOT_COMPFUNC                     "unexpected type"
3030 #define DUK_STR_NOT_NATFUNC                      "unexpected type"
3031 #define DUK_STR_NOT_C_FUNCTION                   "unexpected type"
3032 #define DUK_STR_NOT_FUNCTION                     "unexpected type"
3033 #define DUK_STR_NOT_REGEXP                       "unexpected type"
3034 #define DUK_STR_TOPRIMITIVE_FAILED               "coercion to primitive failed"
3035 #define DUK_STR_NUMBER_OUTSIDE_RANGE             "number outside range"
3036 #define DUK_STR_NOT_OBJECT_COERCIBLE             "not object coercible"
3037 #define DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL      "cannot number coerce Symbol"
3038 #define DUK_STR_CANNOT_STRING_COERCE_SYMBOL      "cannot string coerce Symbol"
3039 #define DUK_STR_STRING_TOO_LONG                  "string too long"
3040 #define DUK_STR_BUFFER_TOO_LONG                  "buffer too long"
3041 #define DUK_STR_ALLOC_FAILED                     "alloc failed"
3042 #define DUK_STR_WRONG_BUFFER_TYPE                "wrong buffer type"
3043 #define DUK_STR_BASE64_ENCODE_FAILED             "base64 encode failed"
3044 #define DUK_STR_SOURCE_DECODE_FAILED             "source decode failed"
3045 #define DUK_STR_UTF8_DECODE_FAILED               "utf-8 decode failed"
3046 #define DUK_STR_BASE64_DECODE_FAILED             "base64 decode failed"
3047 #define DUK_STR_HEX_DECODE_FAILED                "hex decode failed"
3048 #define DUK_STR_INVALID_BYTECODE                 "invalid bytecode"
3049 #define DUK_STR_NO_SOURCECODE                    "no sourcecode"
3050 #define DUK_STR_RESULT_TOO_LONG                  "result too long"
3051 #define DUK_STR_INVALID_CFUNC_RC                 "invalid C function rc"
3052 #define DUK_STR_INVALID_INSTANCEOF_RVAL          "invalid instanceof rval"
3053 #define DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO  "instanceof rval has no .prototype"
3054 
3055 /* JSON */
3056 #define DUK_STR_FMT_PTR                          "%p"
3057 #define DUK_STR_FMT_INVALID_JSON                 "invalid json (at offset %ld)"
3058 #define DUK_STR_JSONDEC_RECLIMIT                 "json decode recursion limit"
3059 #define DUK_STR_JSONENC_RECLIMIT                 "json encode recursion limit"
3060 #define DUK_STR_CYCLIC_INPUT                     "cyclic input"
3061 
3062 /* Object property access */
3063 #define DUK_STR_INVALID_BASE                     "invalid base value"
3064 #define DUK_STR_STRICT_CALLER_READ               "cannot read strict 'caller'"
3065 #define DUK_STR_PROXY_REJECTED                   "proxy rejected"
3066 #define DUK_STR_INVALID_ARRAY_LENGTH             "invalid array length"
3067 #define DUK_STR_SETTER_UNDEFINED                 "setter undefined"
3068 #define DUK_STR_INVALID_DESCRIPTOR               "invalid descriptor"
3069 
3070 /* Proxy */
3071 #define DUK_STR_PROXY_REVOKED                    "proxy revoked"
3072 #define DUK_STR_INVALID_TRAP_RESULT              "invalid trap result"
3073 
3074 /* Variables */
3075 
3076 /* Lexer */
3077 #define DUK_STR_INVALID_ESCAPE                   "invalid escape"
3078 #define DUK_STR_UNTERMINATED_STRING              "unterminated string"
3079 #define DUK_STR_UNTERMINATED_COMMENT             "unterminated comment"
3080 #define DUK_STR_UNTERMINATED_REGEXP              "unterminated regexp"
3081 #define DUK_STR_TOKEN_LIMIT                      "token limit"
3082 #define DUK_STR_REGEXP_SUPPORT_DISABLED          "regexp support disabled"
3083 #define DUK_STR_INVALID_NUMBER_LITERAL           "invalid number literal"
3084 #define DUK_STR_INVALID_TOKEN                    "invalid token"
3085 
3086 /* Compiler */
3087 #define DUK_STR_PARSE_ERROR                      "parse error"
3088 #define DUK_STR_DUPLICATE_LABEL                  "duplicate label"
3089 #define DUK_STR_INVALID_LABEL                    "invalid label"
3090 #define DUK_STR_INVALID_ARRAY_LITERAL            "invalid array literal"
3091 #define DUK_STR_INVALID_OBJECT_LITERAL           "invalid object literal"
3092 #define DUK_STR_INVALID_VAR_DECLARATION          "invalid variable declaration"
3093 #define DUK_STR_CANNOT_DELETE_IDENTIFIER         "cannot delete identifier"
3094 #define DUK_STR_INVALID_EXPRESSION               "invalid expression"
3095 #define DUK_STR_INVALID_LVALUE                   "invalid lvalue"
3096 #define DUK_STR_INVALID_NEWTARGET                "invalid new.target"
3097 #define DUK_STR_EXPECTED_IDENTIFIER              "expected identifier"
3098 #define DUK_STR_EMPTY_EXPR_NOT_ALLOWED           "empty expression not allowed"
3099 #define DUK_STR_INVALID_FOR                      "invalid for statement"
3100 #define DUK_STR_INVALID_SWITCH                   "invalid switch statement"
3101 #define DUK_STR_INVALID_BREAK_CONT_LABEL         "invalid break/continue label"
3102 #define DUK_STR_INVALID_RETURN                   "invalid return"
3103 #define DUK_STR_INVALID_TRY                      "invalid try"
3104 #define DUK_STR_INVALID_THROW                    "invalid throw"
3105 #define DUK_STR_WITH_IN_STRICT_MODE              "with in strict mode"
3106 #define DUK_STR_FUNC_STMT_NOT_ALLOWED            "function statement not allowed"
3107 #define DUK_STR_UNTERMINATED_STMT                "unterminated statement"
3108 #define DUK_STR_INVALID_ARG_NAME                 "invalid argument name"
3109 #define DUK_STR_INVALID_FUNC_NAME                "invalid function name"
3110 #define DUK_STR_INVALID_GETSET_NAME              "invalid getter/setter name"
3111 #define DUK_STR_FUNC_NAME_REQUIRED               "function name required"
3112 
3113 /* RegExp */
3114 #define DUK_STR_INVALID_QUANTIFIER               "invalid regexp quantifier"
3115 #define DUK_STR_INVALID_QUANTIFIER_NO_ATOM       "quantifier without preceding atom"
3116 #define DUK_STR_INVALID_QUANTIFIER_VALUES        "quantifier values invalid (qmin > qmax)"
3117 #define DUK_STR_QUANTIFIER_TOO_MANY_COPIES       "quantifier requires too many atom copies"
3118 #define DUK_STR_UNEXPECTED_CLOSING_PAREN         "unexpected closing parenthesis"
3119 #define DUK_STR_UNEXPECTED_END_OF_PATTERN        "unexpected end of pattern"
3120 #define DUK_STR_UNEXPECTED_REGEXP_TOKEN          "unexpected token in regexp"
3121 #define DUK_STR_INVALID_REGEXP_FLAGS             "invalid regexp flags"
3122 #define DUK_STR_INVALID_REGEXP_ESCAPE            "invalid regexp escape"
3123 #define DUK_STR_INVALID_BACKREFS                 "invalid backreference(s)"
3124 #define DUK_STR_INVALID_REGEXP_CHARACTER         "invalid regexp character"
3125 #define DUK_STR_INVALID_REGEXP_GROUP             "invalid regexp group"
3126 #define DUK_STR_UNTERMINATED_CHARCLASS           "unterminated character class"
3127 #define DUK_STR_INVALID_RANGE                    "invalid range"
3128 
3129 /* Limits */
3130 #define DUK_STR_VALSTACK_LIMIT                   "valstack limit"
3131 #define DUK_STR_CALLSTACK_LIMIT                  "callstack limit"
3132 #define DUK_STR_PROTOTYPE_CHAIN_LIMIT            "prototype chain limit"
3133 #define DUK_STR_BOUND_CHAIN_LIMIT                "function call bound chain limit"
3134 #define DUK_STR_C_CALLSTACK_LIMIT                "C call stack depth limit"
3135 #define DUK_STR_COMPILER_RECURSION_LIMIT         "compiler recursion limit"
3136 #define DUK_STR_BYTECODE_LIMIT                   "bytecode limit"
3137 #define DUK_STR_REG_LIMIT                        "register limit"
3138 #define DUK_STR_TEMP_LIMIT                       "temp limit"
3139 #define DUK_STR_CONST_LIMIT                      "const limit"
3140 #define DUK_STR_FUNC_LIMIT                       "function limit"
3141 #define DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT  "regexp compiler recursion limit"
3142 #define DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT  "regexp executor recursion limit"
3143 #define DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT       "regexp step limit"
3144 
3145 #endif  /* DUK_ERRMSG_H_INCLUDED */
3146 /* #include duk_js_bytecode.h */
3147 #line 1 "duk_js_bytecode.h"
3148 /*
3149  *  ECMAScript bytecode
3150  */
3151 
3152 #if !defined(DUK_JS_BYTECODE_H_INCLUDED)
3153 #define DUK_JS_BYTECODE_H_INCLUDED
3154 
3155 /*
3156  *  Bytecode instruction layout
3157  *  ===========================
3158  *
3159  *  Instructions are unsigned 32-bit integers divided as follows:
3160  *
3161  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3162  *  !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!
3163  *  +-----------------------------------------------+---------------+
3164  *  !       C       !       B       !       A       !       OP      !
3165  *  +-----------------------------------------------+---------------+
3166  *
3167  *  OP (8 bits):  opcode (DUK_OP_*), access should be fastest
3168  *                consecutive opcodes allocated when opcode needs flags
3169  *   A (8 bits):  typically a target register number
3170  *   B (8 bits):  typically first source register/constant number
3171  *   C (8 bits):  typically second source register/constant number
3172  *
3173  *  Some instructions combine BC or ABC together for larger parameter values.
3174  *  Signed integers (e.g. jump offsets) are encoded as unsigned, with an
3175  *  opcode specific bias.
3176  *
3177  *  Some opcodes have flags which are handled by allocating consecutive
3178  *  opcodes to make space for 1-N flags.  Flags can also be e.g. in the 'A'
3179  *  field when there's room for the specific opcode.
3180  *
3181  *  For example, if three flags were needed, they could be allocated from
3182  *  the opcode field as follows:
3183  *
3184  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3185  *  !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!
3186  *  +-----------------------------------------------+---------------+
3187  *  !       C       !       B       !       A       !    OP   !Z!Y!X!
3188  *  +-----------------------------------------------+---------------+
3189  *
3190  *  Some opcodes accept a reg/const argument which is handled by allocating
3191  *  flags in the OP field, see DUK_BC_ISREG() and DUK_BC_ISCONST().  The
3192  *  following convention is shared by most opcodes, so that the compiler
3193  *  can handle reg/const flagging without opcode specific code paths:
3194  *
3195  *  !3!3!2!2!2!2!2!2!2!2!2!2!1!1!1!1!1!1!1!1!1!1! ! ! ! ! ! ! ! ! ! !
3196  *  !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!
3197  *  +-----------------------------------------------+---------------+
3198  *  !       C       !       B       !       A       !     OP    !Y!X!
3199  *  +-----------------------------------------------+---------------+
3200  *
3201  *    X  1=B is const, 0=B is reg
3202  *    Y  1=C is const, 0=C is reg
3203  *
3204  *    In effect OP, OP + 1, OP + 2, and OP + 3 are allocated from the
3205  *    8-bit opcode space for a single logical opcode.  The base opcode
3206  *    number should be divisible by 4.  If the opcode is called 'FOO'
3207  *    the following opcode constants would be defined:
3208  *
3209  *      DUK_OP_FOO     100       // base opcode number
3210  *      DUK_OP_FOO_RR  100       // FOO, B=reg, C=reg
3211  *      DUK_OP_FOO_CR  101       // FOO, B=const, C=reg
3212  *      DUK_OP_FOO_RC  102       // FOO, B=reg, C=const
3213  *      DUK_OP_FOO_CC  103       // FOO, B=const, C=const
3214  *
3215  *  If only B or C is a reg/const, the unused opcode combinations can be
3216  *  used for other opcodes (which take no reg/const argument).  However,
3217  *  such opcode values are initially reserved, at least while opcode space
3218  *  is available.  For example, if 'BAR' uses B for a register field and
3219  *  C is a reg/const:
3220  *
3221  *      DUK_OP_BAR            116    // base opcode number
3222  *      DUK_OP_BAR_RR         116    // BAR, B=reg, C=reg
3223  *      DUK_OP_BAR_CR_UNUSED  117    // unused, could be repurposed
3224  *      DUK_OP_BAR_RC         118    // BAR, B=reg, C=const
3225  *      DUK_OP_BAR_CC_UNUSED  119    // unused, could be repurposed
3226  *
3227  *  Macro naming is a bit misleading, e.g. "ABC" in macro name but the
3228  *  field layout is concretely "CBA" in the register.
3229  */
3230 
3231 typedef duk_uint32_t duk_instr_t;
3232 
3233 #define DUK_BC_SHIFT_OP             0
3234 #define DUK_BC_SHIFT_A              8
3235 #define DUK_BC_SHIFT_B              16
3236 #define DUK_BC_SHIFT_C              24
3237 #define DUK_BC_SHIFT_BC             DUK_BC_SHIFT_B
3238 #define DUK_BC_SHIFT_ABC            DUK_BC_SHIFT_A
3239 
3240 #define DUK_BC_UNSHIFTED_MASK_OP    0xffUL
3241 #define DUK_BC_UNSHIFTED_MASK_A     0xffUL
3242 #define DUK_BC_UNSHIFTED_MASK_B     0xffUL
3243 #define DUK_BC_UNSHIFTED_MASK_C     0xffUL
3244 #define DUK_BC_UNSHIFTED_MASK_BC    0xffffUL
3245 #define DUK_BC_UNSHIFTED_MASK_ABC   0xffffffUL
3246 
3247 #define DUK_BC_SHIFTED_MASK_OP      (DUK_BC_UNSHIFTED_MASK_OP << DUK_BC_SHIFT_OP)
3248 #define DUK_BC_SHIFTED_MASK_A       (DUK_BC_UNSHIFTED_MASK_A << DUK_BC_SHIFT_A)
3249 #define DUK_BC_SHIFTED_MASK_B       (DUK_BC_UNSHIFTED_MASK_B << DUK_BC_SHIFT_B)
3250 #define DUK_BC_SHIFTED_MASK_C       (DUK_BC_UNSHIFTED_MASK_C << DUK_BC_SHIFT_C)
3251 #define DUK_BC_SHIFTED_MASK_BC      (DUK_BC_UNSHIFTED_MASK_BC << DUK_BC_SHIFT_BC)
3252 #define DUK_BC_SHIFTED_MASK_ABC     (DUK_BC_UNSHIFTED_MASK_ABC << DUK_BC_SHIFT_ABC)
3253 
3254 #define DUK_DEC_OP(x)               ((x) & 0xffUL)
3255 #define DUK_DEC_A(x)                (((x) >> 8) & 0xffUL)
3256 #define DUK_DEC_B(x)                (((x) >> 16) & 0xffUL)
3257 #define DUK_DEC_C(x)                (((x) >> 24) & 0xffUL)
3258 #define DUK_DEC_BC(x)               (((x) >> 16) & 0xffffUL)
3259 #define DUK_DEC_ABC(x)              (((x) >> 8) & 0xffffffUL)
3260 
3261 #define DUK_ENC_OP(op)              ((duk_instr_t) (op))
3262 #define DUK_ENC_OP_ABC(op,abc)      ((duk_instr_t) ( \
3263                                         (((duk_instr_t) (abc)) << 8) | \
3264                                         ((duk_instr_t) (op)) \
3265                                     ))
3266 #define DUK_ENC_OP_A_BC(op,a,bc)    ((duk_instr_t) ( \
3267                                         (((duk_instr_t) (bc)) << 16) | \
3268                                         (((duk_instr_t) (a)) << 8) | \
3269                                         ((duk_instr_t) (op)) \
3270                                     ))
3271 #define DUK_ENC_OP_A_B_C(op,a,b,c)  ((duk_instr_t) ( \
3272                                         (((duk_instr_t) (c)) << 24) | \
3273                                         (((duk_instr_t) (b)) << 16) | \
3274                                         (((duk_instr_t) (a)) << 8) | \
3275                                         ((duk_instr_t) (op)) \
3276                                     ))
3277 #define DUK_ENC_OP_A_B(op,a,b)      DUK_ENC_OP_A_B_C((op),(a),(b),0)
3278 #define DUK_ENC_OP_A(op,a)          DUK_ENC_OP_A_B_C((op),(a),0,0)
3279 #define DUK_ENC_OP_BC(op,bc)        DUK_ENC_OP_A_BC((op),0,(bc))
3280 
3281 /* Get opcode base value with B/C reg/const flags cleared. */
3282 #define DUK_BC_NOREGCONST_OP(op)    ((op) & 0xfc)
3283 
3284 /* Constants should be signed so that signed arithmetic involving them
3285  * won't cause values to be coerced accidentally to unsigned.
3286  */
3287 #define DUK_BC_OP_MIN               0
3288 #define DUK_BC_OP_MAX               0xffL
3289 #define DUK_BC_A_MIN                0
3290 #define DUK_BC_A_MAX                0xffL
3291 #define DUK_BC_B_MIN                0
3292 #define DUK_BC_B_MAX                0xffL
3293 #define DUK_BC_C_MIN                0
3294 #define DUK_BC_C_MAX                0xffL
3295 #define DUK_BC_BC_MIN               0
3296 #define DUK_BC_BC_MAX               0xffffL
3297 #define DUK_BC_ABC_MIN              0
3298 #define DUK_BC_ABC_MAX              0xffffffL
3299 
3300 /* Masks for B/C reg/const indicator in opcode field. */
3301 #define DUK_BC_REGCONST_B           (0x01UL)
3302 #define DUK_BC_REGCONST_C           (0x02UL)
3303 
3304 /* Misc. masks for opcode field. */
3305 #define DUK_BC_INCDECP_FLAG_DEC     (0x04UL)
3306 #define DUK_BC_INCDECP_FLAG_POST    (0x08UL)
3307 
3308 /* Opcodes. */
3309 #define DUK_OP_LDREG                0
3310 #define DUK_OP_STREG                1
3311 #define DUK_OP_JUMP                 2
3312 #define DUK_OP_LDCONST              3
3313 #define DUK_OP_LDINT                4
3314 #define DUK_OP_LDINTX               5
3315 #define DUK_OP_LDTHIS               6
3316 #define DUK_OP_LDUNDEF              7
3317 #define DUK_OP_LDNULL               8
3318 #define DUK_OP_LDTRUE               9
3319 #define DUK_OP_LDFALSE              10
3320 #define DUK_OP_GETVAR               11
3321 #define DUK_OP_BNOT                 12
3322 #define DUK_OP_LNOT                 13
3323 #define DUK_OP_UNM                  14
3324 #define DUK_OP_UNP                  15
3325 #define DUK_OP_EQ                   16
3326 #define DUK_OP_EQ_RR                16
3327 #define DUK_OP_EQ_CR                17
3328 #define DUK_OP_EQ_RC                18
3329 #define DUK_OP_EQ_CC                19
3330 #define DUK_OP_NEQ                  20
3331 #define DUK_OP_NEQ_RR               20
3332 #define DUK_OP_NEQ_CR               21
3333 #define DUK_OP_NEQ_RC               22
3334 #define DUK_OP_NEQ_CC               23
3335 #define DUK_OP_SEQ                  24
3336 #define DUK_OP_SEQ_RR               24
3337 #define DUK_OP_SEQ_CR               25
3338 #define DUK_OP_SEQ_RC               26
3339 #define DUK_OP_SEQ_CC               27
3340 #define DUK_OP_SNEQ                 28
3341 #define DUK_OP_SNEQ_RR              28
3342 #define DUK_OP_SNEQ_CR              29
3343 #define DUK_OP_SNEQ_RC              30
3344 #define DUK_OP_SNEQ_CC              31
3345 #define DUK_OP_GT                   32
3346 #define DUK_OP_GT_RR                32
3347 #define DUK_OP_GT_CR                33
3348 #define DUK_OP_GT_RC                34
3349 #define DUK_OP_GT_CC                35
3350 #define DUK_OP_GE                   36
3351 #define DUK_OP_GE_RR                36
3352 #define DUK_OP_GE_CR                37
3353 #define DUK_OP_GE_RC                38
3354 #define DUK_OP_GE_CC                39
3355 #define DUK_OP_LT                   40
3356 #define DUK_OP_LT_RR                40
3357 #define DUK_OP_LT_CR                41
3358 #define DUK_OP_LT_RC                42
3359 #define DUK_OP_LT_CC                43
3360 #define DUK_OP_LE                   44
3361 #define DUK_OP_LE_RR                44
3362 #define DUK_OP_LE_CR                45
3363 #define DUK_OP_LE_RC                46
3364 #define DUK_OP_LE_CC                47
3365 #define DUK_OP_IFTRUE               48
3366 #define DUK_OP_IFTRUE_R             48
3367 #define DUK_OP_IFTRUE_C             49
3368 #define DUK_OP_IFFALSE              50
3369 #define DUK_OP_IFFALSE_R            50
3370 #define DUK_OP_IFFALSE_C            51
3371 #define DUK_OP_ADD                  52
3372 #define DUK_OP_ADD_RR               52
3373 #define DUK_OP_ADD_CR               53
3374 #define DUK_OP_ADD_RC               54
3375 #define DUK_OP_ADD_CC               55
3376 #define DUK_OP_SUB                  56
3377 #define DUK_OP_SUB_RR               56
3378 #define DUK_OP_SUB_CR               57
3379 #define DUK_OP_SUB_RC               58
3380 #define DUK_OP_SUB_CC               59
3381 #define DUK_OP_MUL                  60
3382 #define DUK_OP_MUL_RR               60
3383 #define DUK_OP_MUL_CR               61
3384 #define DUK_OP_MUL_RC               62
3385 #define DUK_OP_MUL_CC               63
3386 #define DUK_OP_DIV                  64
3387 #define DUK_OP_DIV_RR               64
3388 #define DUK_OP_DIV_CR               65
3389 #define DUK_OP_DIV_RC               66
3390 #define DUK_OP_DIV_CC               67
3391 #define DUK_OP_MOD                  68
3392 #define DUK_OP_MOD_RR               68
3393 #define DUK_OP_MOD_CR               69
3394 #define DUK_OP_MOD_RC               70
3395 #define DUK_OP_MOD_CC               71
3396 #define DUK_OP_EXP                  72
3397 #define DUK_OP_EXP_RR               72
3398 #define DUK_OP_EXP_CR               73
3399 #define DUK_OP_EXP_RC               74
3400 #define DUK_OP_EXP_CC               75
3401 #define DUK_OP_BAND                 76
3402 #define DUK_OP_BAND_RR              76
3403 #define DUK_OP_BAND_CR              77
3404 #define DUK_OP_BAND_RC              78
3405 #define DUK_OP_BAND_CC              79
3406 #define DUK_OP_BOR                  80
3407 #define DUK_OP_BOR_RR               80
3408 #define DUK_OP_BOR_CR               81
3409 #define DUK_OP_BOR_RC               82
3410 #define DUK_OP_BOR_CC               83
3411 #define DUK_OP_BXOR                 84
3412 #define DUK_OP_BXOR_RR              84
3413 #define DUK_OP_BXOR_CR              85
3414 #define DUK_OP_BXOR_RC              86
3415 #define DUK_OP_BXOR_CC              87
3416 #define DUK_OP_BASL                 88
3417 #define DUK_OP_BASL_RR              88
3418 #define DUK_OP_BASL_CR              89
3419 #define DUK_OP_BASL_RC              90
3420 #define DUK_OP_BASL_CC              91
3421 #define DUK_OP_BLSR                 92
3422 #define DUK_OP_BLSR_RR              92
3423 #define DUK_OP_BLSR_CR              93
3424 #define DUK_OP_BLSR_RC              94
3425 #define DUK_OP_BLSR_CC              95
3426 #define DUK_OP_BASR                 96
3427 #define DUK_OP_BASR_RR              96
3428 #define DUK_OP_BASR_CR              97
3429 #define DUK_OP_BASR_RC              98
3430 #define DUK_OP_BASR_CC              99
3431 #define DUK_OP_INSTOF               100
3432 #define DUK_OP_INSTOF_RR            100
3433 #define DUK_OP_INSTOF_CR            101
3434 #define DUK_OP_INSTOF_RC            102
3435 #define DUK_OP_INSTOF_CC            103
3436 #define DUK_OP_IN                   104
3437 #define DUK_OP_IN_RR                104
3438 #define DUK_OP_IN_CR                105
3439 #define DUK_OP_IN_RC                106
3440 #define DUK_OP_IN_CC                107
3441 #define DUK_OP_GETPROP              108
3442 #define DUK_OP_GETPROP_RR           108
3443 #define DUK_OP_GETPROP_CR           109
3444 #define DUK_OP_GETPROP_RC           110
3445 #define DUK_OP_GETPROP_CC           111
3446 #define DUK_OP_PUTPROP              112
3447 #define DUK_OP_PUTPROP_RR           112
3448 #define DUK_OP_PUTPROP_CR           113
3449 #define DUK_OP_PUTPROP_RC           114
3450 #define DUK_OP_PUTPROP_CC           115
3451 #define DUK_OP_DELPROP              116
3452 #define DUK_OP_DELPROP_RR           116
3453 #define DUK_OP_DELPROP_CR_UNUSED    117  /* unused now */
3454 #define DUK_OP_DELPROP_RC           118
3455 #define DUK_OP_DELPROP_CC_UNUSED    119  /* unused now */
3456 #define DUK_OP_PREINCR              120  /* pre/post opcode values have constraints, */
3457 #define DUK_OP_PREDECR              121  /* see duk_js_executor.c and duk_js_compiler.c. */
3458 #define DUK_OP_POSTINCR             122
3459 #define DUK_OP_POSTDECR             123
3460 #define DUK_OP_PREINCV              124
3461 #define DUK_OP_PREDECV              125
3462 #define DUK_OP_POSTINCV             126
3463 #define DUK_OP_POSTDECV             127
3464 #define DUK_OP_PREINCP              128  /* pre/post inc/dec prop opcodes have constraints */
3465 #define DUK_OP_PREINCP_RR           128
3466 #define DUK_OP_PREINCP_CR           129
3467 #define DUK_OP_PREINCP_RC           130
3468 #define DUK_OP_PREINCP_CC           131
3469 #define DUK_OP_PREDECP              132
3470 #define DUK_OP_PREDECP_RR           132
3471 #define DUK_OP_PREDECP_CR           133
3472 #define DUK_OP_PREDECP_RC           134
3473 #define DUK_OP_PREDECP_CC           135
3474 #define DUK_OP_POSTINCP             136
3475 #define DUK_OP_POSTINCP_RR          136
3476 #define DUK_OP_POSTINCP_CR          137
3477 #define DUK_OP_POSTINCP_RC          138
3478 #define DUK_OP_POSTINCP_CC          139
3479 #define DUK_OP_POSTDECP             140
3480 #define DUK_OP_POSTDECP_RR          140
3481 #define DUK_OP_POSTDECP_CR          141
3482 #define DUK_OP_POSTDECP_RC          142
3483 #define DUK_OP_POSTDECP_CC          143
3484 #define DUK_OP_DECLVAR              144
3485 #define DUK_OP_DECLVAR_RR           144
3486 #define DUK_OP_DECLVAR_CR           145
3487 #define DUK_OP_DECLVAR_RC           146
3488 #define DUK_OP_DECLVAR_CC           147
3489 #define DUK_OP_REGEXP               148
3490 #define DUK_OP_REGEXP_RR            148
3491 #define DUK_OP_REGEXP_CR            149
3492 #define DUK_OP_REGEXP_RC            150
3493 #define DUK_OP_REGEXP_CC            151
3494 #define DUK_OP_CLOSURE              152
3495 #define DUK_OP_TYPEOF               153
3496 #define DUK_OP_TYPEOFID             154
3497 #define DUK_OP_PUTVAR               155
3498 #define DUK_OP_DELVAR               156
3499 #define DUK_OP_RETREG               157
3500 #define DUK_OP_RETUNDEF             158
3501 #define DUK_OP_RETCONST             159
3502 #define DUK_OP_RETCONSTN            160  /* return const without incref (e.g. number) */
3503 #define DUK_OP_LABEL                161
3504 #define DUK_OP_ENDLABEL             162
3505 #define DUK_OP_BREAK                163
3506 #define DUK_OP_CONTINUE             164
3507 #define DUK_OP_TRYCATCH             165
3508 #define DUK_OP_ENDTRY               166
3509 #define DUK_OP_ENDCATCH             167
3510 #define DUK_OP_ENDFIN               168
3511 #define DUK_OP_THROW                169
3512 #define DUK_OP_INVLHS               170
3513 #define DUK_OP_CSREG                171
3514 #define DUK_OP_CSVAR                172
3515 #define DUK_OP_CSVAR_RR             172
3516 #define DUK_OP_CSVAR_CR             173
3517 #define DUK_OP_CSVAR_RC             174
3518 #define DUK_OP_CSVAR_CC             175
3519 #define DUK_OP_CALL0                176  /* DUK_OP_CALL0 & 0x0F must be zero. */
3520 #define DUK_OP_CALL1                177
3521 #define DUK_OP_CALL2                178
3522 #define DUK_OP_CALL3                179
3523 #define DUK_OP_CALL4                180
3524 #define DUK_OP_CALL5                181
3525 #define DUK_OP_CALL6                182
3526 #define DUK_OP_CALL7                183
3527 #define DUK_OP_CALL8                184
3528 #define DUK_OP_CALL9                185
3529 #define DUK_OP_CALL10               186
3530 #define DUK_OP_CALL11               187
3531 #define DUK_OP_CALL12               188
3532 #define DUK_OP_CALL13               189
3533 #define DUK_OP_CALL14               190
3534 #define DUK_OP_CALL15               191
3535 #define DUK_OP_NEWOBJ               192
3536 #define DUK_OP_NEWARR               193
3537 #define DUK_OP_MPUTOBJ              194
3538 #define DUK_OP_MPUTOBJI             195
3539 #define DUK_OP_INITSET              196
3540 #define DUK_OP_INITGET              197
3541 #define DUK_OP_MPUTARR              198
3542 #define DUK_OP_MPUTARRI             199
3543 #define DUK_OP_SETALEN              200
3544 #define DUK_OP_INITENUM             201
3545 #define DUK_OP_NEXTENUM             202
3546 #define DUK_OP_NEWTARGET            203
3547 #define DUK_OP_DEBUGGER             204
3548 #define DUK_OP_NOP                  205
3549 #define DUK_OP_INVALID              206
3550 #define DUK_OP_UNUSED207            207
3551 #define DUK_OP_GETPROPC             208
3552 #define DUK_OP_GETPROPC_RR          208
3553 #define DUK_OP_GETPROPC_CR          209
3554 #define DUK_OP_GETPROPC_RC          210
3555 #define DUK_OP_GETPROPC_CC          211
3556 #define DUK_OP_UNUSED212            212
3557 #define DUK_OP_UNUSED213            213
3558 #define DUK_OP_UNUSED214            214
3559 #define DUK_OP_UNUSED215            215
3560 #define DUK_OP_UNUSED216            216
3561 #define DUK_OP_UNUSED217            217
3562 #define DUK_OP_UNUSED218            218
3563 #define DUK_OP_UNUSED219            219
3564 #define DUK_OP_UNUSED220            220
3565 #define DUK_OP_UNUSED221            221
3566 #define DUK_OP_UNUSED222            222
3567 #define DUK_OP_UNUSED223            223
3568 #define DUK_OP_UNUSED224            224
3569 #define DUK_OP_UNUSED225            225
3570 #define DUK_OP_UNUSED226            226
3571 #define DUK_OP_UNUSED227            227
3572 #define DUK_OP_UNUSED228            228
3573 #define DUK_OP_UNUSED229            229
3574 #define DUK_OP_UNUSED230            230
3575 #define DUK_OP_UNUSED231            231
3576 #define DUK_OP_UNUSED232            232
3577 #define DUK_OP_UNUSED233            233
3578 #define DUK_OP_UNUSED234            234
3579 #define DUK_OP_UNUSED235            235
3580 #define DUK_OP_UNUSED236            236
3581 #define DUK_OP_UNUSED237            237
3582 #define DUK_OP_UNUSED238            238
3583 #define DUK_OP_UNUSED239            239
3584 #define DUK_OP_UNUSED240            240
3585 #define DUK_OP_UNUSED241            241
3586 #define DUK_OP_UNUSED242            242
3587 #define DUK_OP_UNUSED243            243
3588 #define DUK_OP_UNUSED244            244
3589 #define DUK_OP_UNUSED245            245
3590 #define DUK_OP_UNUSED246            246
3591 #define DUK_OP_UNUSED247            247
3592 #define DUK_OP_UNUSED248            248
3593 #define DUK_OP_UNUSED249            249
3594 #define DUK_OP_UNUSED250            250
3595 #define DUK_OP_UNUSED251            251
3596 #define DUK_OP_UNUSED252            252
3597 #define DUK_OP_UNUSED253            253
3598 #define DUK_OP_UNUSED254            254
3599 #define DUK_OP_UNUSED255            255
3600 #define DUK_OP_NONE                 256  /* dummy value used as marker (doesn't fit in 8-bit field) */
3601 
3602 /* XXX: Allocate flags from opcode field?  Would take 16 opcode slots
3603  * but avoids shuffling in more cases.  Maybe not worth it.
3604  */
3605 /* DUK_OP_TRYCATCH flags in A. */
3606 #define DUK_BC_TRYCATCH_FLAG_HAVE_CATCH     (1U << 0)
3607 #define DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY   (1U << 1)
3608 #define DUK_BC_TRYCATCH_FLAG_CATCH_BINDING  (1U << 2)
3609 #define DUK_BC_TRYCATCH_FLAG_WITH_BINDING   (1U << 3)
3610 
3611 /* DUK_OP_DECLVAR flags in A; bottom bits are reserved for propdesc flags
3612  * (DUK_PROPDESC_FLAG_XXX).
3613  */
3614 #define DUK_BC_DECLVAR_FLAG_FUNC_DECL       (1U << 4)  /* function declaration */
3615 
3616 /* DUK_OP_CALLn flags, part of opcode field.  Three lowest bits must match
3617  * DUK_CALL_FLAG_xxx directly.
3618  */
3619 #define DUK_BC_CALL_FLAG_TAILCALL           (1U << 0)
3620 #define DUK_BC_CALL_FLAG_CONSTRUCT          (1U << 1)
3621 #define DUK_BC_CALL_FLAG_CALLED_AS_EVAL     (1U << 2)
3622 #define DUK_BC_CALL_FLAG_INDIRECT           (1U << 3)
3623 
3624 /* Misc constants and helper macros. */
3625 #define DUK_BC_LDINT_BIAS           (1L << 15)
3626 #define DUK_BC_LDINTX_SHIFT         16
3627 #define DUK_BC_JUMP_BIAS            (1L << 23)
3628 
3629 #endif  /* DUK_JS_BYTECODE_H_INCLUDED */
3630 /* #include duk_lexer.h */
3631 #line 1 "duk_lexer.h"
3632 /*
3633  *  Lexer defines.
3634  */
3635 
3636 #if !defined(DUK_LEXER_H_INCLUDED)
3637 #define DUK_LEXER_H_INCLUDED
3638 
3639 typedef void (*duk_re_range_callback)(void *user, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct);
3640 
3641 /*
3642  *  A token is interpreted as any possible production of InputElementDiv
3643  *  and InputElementRegExp, see E5 Section 7 in its entirety.  Note that
3644  *  the E5 "Token" production does not cover all actual tokens of the
3645  *  language (which is explicitly stated in the specification, Section 7.5).
3646  *  Null and boolean literals are defined as part of both ReservedWord
3647  *  (E5 Section 7.6.1) and Literal (E5 Section 7.8) productions.  Here,
3648  *  null and boolean values have literal tokens, and are not reserved
3649  *  words.
3650  *
3651  *  Decimal literal negative/positive sign is -not- part of DUK_TOK_NUMBER.
3652  *  The number tokens always have a non-negative value.  The unary minus
3653  *  operator in "-1.0" is optimized during compilation to yield a single
3654  *  negative constant.
3655  *
3656  *  Token numbering is free except that reserved words are required to be
3657  *  in a continuous range and in a particular order.  See genstrings.py.
3658  */
3659 
3660 #define DUK_LEXER_INITCTX(ctx)        duk_lexer_initctx((ctx))
3661 
3662 #define DUK_LEXER_SETPOINT(ctx,pt)    duk_lexer_setpoint((ctx), (pt))
3663 
3664 #define DUK_LEXER_GETPOINT(ctx,pt)    duk_lexer_getpoint((ctx), (pt))
3665 
3666 /* Currently 6 characters of lookup are actually needed (duk_lexer.c). */
3667 #define DUK_LEXER_WINDOW_SIZE                     6
3668 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
3669 #define DUK_LEXER_BUFFER_SIZE                     64
3670 #endif
3671 
3672 #define DUK_TOK_MINVAL                            0
3673 
3674 /* returned after EOF (infinite amount) */
3675 #define DUK_TOK_EOF                               0
3676 
3677 /* identifier names (E5 Section 7.6) */
3678 #define DUK_TOK_IDENTIFIER                        1
3679 
3680 /* reserved words: keywords */
3681 #define DUK_TOK_START_RESERVED                    2
3682 #define DUK_TOK_BREAK                             2
3683 #define DUK_TOK_CASE                              3
3684 #define DUK_TOK_CATCH                             4
3685 #define DUK_TOK_CONTINUE                          5
3686 #define DUK_TOK_DEBUGGER                          6
3687 #define DUK_TOK_DEFAULT                           7
3688 #define DUK_TOK_DELETE                            8
3689 #define DUK_TOK_DO                                9
3690 #define DUK_TOK_ELSE                              10
3691 #define DUK_TOK_FINALLY                           11
3692 #define DUK_TOK_FOR                               12
3693 #define DUK_TOK_FUNCTION                          13
3694 #define DUK_TOK_IF                                14
3695 #define DUK_TOK_IN                                15
3696 #define DUK_TOK_INSTANCEOF                        16
3697 #define DUK_TOK_NEW                               17
3698 #define DUK_TOK_RETURN                            18
3699 #define DUK_TOK_SWITCH                            19
3700 #define DUK_TOK_THIS                              20
3701 #define DUK_TOK_THROW                             21
3702 #define DUK_TOK_TRY                               22
3703 #define DUK_TOK_TYPEOF                            23
3704 #define DUK_TOK_VAR                               24
3705 #define DUK_TOK_CONST                             25
3706 #define DUK_TOK_VOID                              26
3707 #define DUK_TOK_WHILE                             27
3708 #define DUK_TOK_WITH                              28
3709 
3710 /* reserved words: future reserved words */
3711 #define DUK_TOK_CLASS                             29
3712 #define DUK_TOK_ENUM                              30
3713 #define DUK_TOK_EXPORT                            31
3714 #define DUK_TOK_EXTENDS                           32
3715 #define DUK_TOK_IMPORT                            33
3716 #define DUK_TOK_SUPER                             34
3717 
3718 /* "null", "true", and "false" are always reserved words.
3719  * Note that "get" and "set" are not!
3720  */
3721 #define DUK_TOK_NULL                              35
3722 #define DUK_TOK_TRUE                              36
3723 #define DUK_TOK_FALSE                             37
3724 
3725 /* reserved words: additional future reserved words in strict mode */
3726 #define DUK_TOK_START_STRICT_RESERVED             38  /* inclusive */
3727 #define DUK_TOK_IMPLEMENTS                        38
3728 #define DUK_TOK_INTERFACE                         39
3729 #define DUK_TOK_LET                               40
3730 #define DUK_TOK_PACKAGE                           41
3731 #define DUK_TOK_PRIVATE                           42
3732 #define DUK_TOK_PROTECTED                         43
3733 #define DUK_TOK_PUBLIC                            44
3734 #define DUK_TOK_STATIC                            45
3735 #define DUK_TOK_YIELD                             46
3736 
3737 #define DUK_TOK_END_RESERVED                      47  /* exclusive */
3738 
3739 /* "get" and "set" are tokens but NOT ReservedWords.  They are currently
3740  * parsed and identifiers and these defines are actually now unused.
3741  */
3742 #define DUK_TOK_GET                               47
3743 #define DUK_TOK_SET                               48
3744 
3745 /* punctuators (unlike the spec, also includes "/" and "/=") */
3746 #define DUK_TOK_LCURLY                            49
3747 #define DUK_TOK_RCURLY                            50
3748 #define DUK_TOK_LBRACKET                          51
3749 #define DUK_TOK_RBRACKET                          52
3750 #define DUK_TOK_LPAREN                            53
3751 #define DUK_TOK_RPAREN                            54
3752 #define DUK_TOK_PERIOD                            55
3753 #define DUK_TOK_SEMICOLON                         56
3754 #define DUK_TOK_COMMA                             57
3755 #define DUK_TOK_LT                                58
3756 #define DUK_TOK_GT                                59
3757 #define DUK_TOK_LE                                60
3758 #define DUK_TOK_GE                                61
3759 #define DUK_TOK_EQ                                62
3760 #define DUK_TOK_NEQ                               63
3761 #define DUK_TOK_SEQ                               64
3762 #define DUK_TOK_SNEQ                              65
3763 #define DUK_TOK_ADD                               66
3764 #define DUK_TOK_SUB                               67
3765 #define DUK_TOK_MUL                               68
3766 #define DUK_TOK_DIV                               69
3767 #define DUK_TOK_MOD                               70
3768 #define DUK_TOK_EXP                               71
3769 #define DUK_TOK_INCREMENT                         72
3770 #define DUK_TOK_DECREMENT                         73
3771 #define DUK_TOK_ALSHIFT                           74   /* named "arithmetic" because result is signed */
3772 #define DUK_TOK_ARSHIFT                           75
3773 #define DUK_TOK_RSHIFT                            76
3774 #define DUK_TOK_BAND                              77
3775 #define DUK_TOK_BOR                               78
3776 #define DUK_TOK_BXOR                              79
3777 #define DUK_TOK_LNOT                              80
3778 #define DUK_TOK_BNOT                              81
3779 #define DUK_TOK_LAND                              82
3780 #define DUK_TOK_LOR                               83
3781 #define DUK_TOK_QUESTION                          84
3782 #define DUK_TOK_COLON                             85
3783 #define DUK_TOK_EQUALSIGN                         86
3784 #define DUK_TOK_ADD_EQ                            87
3785 #define DUK_TOK_SUB_EQ                            88
3786 #define DUK_TOK_MUL_EQ                            89
3787 #define DUK_TOK_DIV_EQ                            90
3788 #define DUK_TOK_MOD_EQ                            91
3789 #define DUK_TOK_EXP_EQ                            92
3790 #define DUK_TOK_ALSHIFT_EQ                        93
3791 #define DUK_TOK_ARSHIFT_EQ                        94
3792 #define DUK_TOK_RSHIFT_EQ                         95
3793 #define DUK_TOK_BAND_EQ                           96
3794 #define DUK_TOK_BOR_EQ                            97
3795 #define DUK_TOK_BXOR_EQ                           98
3796 
3797 /* literals (E5 Section 7.8), except null, true, false, which are treated
3798  * like reserved words (above).
3799  */
3800 #define DUK_TOK_NUMBER                            99
3801 #define DUK_TOK_STRING                            100
3802 #define DUK_TOK_REGEXP                            101
3803 
3804 #define DUK_TOK_MAXVAL                            101  /* inclusive */
3805 
3806 #define DUK_TOK_INVALID                           DUK_SMALL_UINT_MAX
3807 
3808 /* Convert heap string index to a token (reserved words) */
3809 #define DUK_STRIDX_TO_TOK(x)                        ((x) - DUK_STRIDX_START_RESERVED + DUK_TOK_START_RESERVED)
3810 
3811 /* Sanity check */
3812 #if (DUK_TOK_MAXVAL > 255)
3813 #error DUK_TOK_MAXVAL too large, code assumes it fits into 8 bits
3814 #endif
3815 
3816 /* Sanity checks for string and token defines */
3817 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_BREAK) != DUK_TOK_BREAK)
3818 #error mismatch in token defines
3819 #endif
3820 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CASE) != DUK_TOK_CASE)
3821 #error mismatch in token defines
3822 #endif
3823 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CATCH) != DUK_TOK_CATCH)
3824 #error mismatch in token defines
3825 #endif
3826 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONTINUE) != DUK_TOK_CONTINUE)
3827 #error mismatch in token defines
3828 #endif
3829 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEBUGGER) != DUK_TOK_DEBUGGER)
3830 #error mismatch in token defines
3831 #endif
3832 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DEFAULT) != DUK_TOK_DEFAULT)
3833 #error mismatch in token defines
3834 #endif
3835 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DELETE) != DUK_TOK_DELETE)
3836 #error mismatch in token defines
3837 #endif
3838 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_DO) != DUK_TOK_DO)
3839 #error mismatch in token defines
3840 #endif
3841 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ELSE) != DUK_TOK_ELSE)
3842 #error mismatch in token defines
3843 #endif
3844 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FINALLY) != DUK_TOK_FINALLY)
3845 #error mismatch in token defines
3846 #endif
3847 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FOR) != DUK_TOK_FOR)
3848 #error mismatch in token defines
3849 #endif
3850 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_FUNCTION) != DUK_TOK_FUNCTION)
3851 #error mismatch in token defines
3852 #endif
3853 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IF) != DUK_TOK_IF)
3854 #error mismatch in token defines
3855 #endif
3856 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IN) != DUK_TOK_IN)
3857 #error mismatch in token defines
3858 #endif
3859 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INSTANCEOF) != DUK_TOK_INSTANCEOF)
3860 #error mismatch in token defines
3861 #endif
3862 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_NEW) != DUK_TOK_NEW)
3863 #error mismatch in token defines
3864 #endif
3865 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_RETURN) != DUK_TOK_RETURN)
3866 #error mismatch in token defines
3867 #endif
3868 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SWITCH) != DUK_TOK_SWITCH)
3869 #error mismatch in token defines
3870 #endif
3871 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THIS) != DUK_TOK_THIS)
3872 #error mismatch in token defines
3873 #endif
3874 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_THROW) != DUK_TOK_THROW)
3875 #error mismatch in token defines
3876 #endif
3877 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRY) != DUK_TOK_TRY)
3878 #error mismatch in token defines
3879 #endif
3880 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TYPEOF) != DUK_TOK_TYPEOF)
3881 #error mismatch in token defines
3882 #endif
3883 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VAR) != DUK_TOK_VAR)
3884 #error mismatch in token defines
3885 #endif
3886 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_VOID) != DUK_TOK_VOID)
3887 #error mismatch in token defines
3888 #endif
3889 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WHILE) != DUK_TOK_WHILE)
3890 #error mismatch in token defines
3891 #endif
3892 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_WITH) != DUK_TOK_WITH)
3893 #error mismatch in token defines
3894 #endif
3895 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CLASS) != DUK_TOK_CLASS)
3896 #error mismatch in token defines
3897 #endif
3898 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_CONST) != DUK_TOK_CONST)
3899 #error mismatch in token defines
3900 #endif
3901 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_ENUM) != DUK_TOK_ENUM)
3902 #error mismatch in token defines
3903 #endif
3904 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXPORT) != DUK_TOK_EXPORT)
3905 #error mismatch in token defines
3906 #endif
3907 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_EXTENDS) != DUK_TOK_EXTENDS)
3908 #error mismatch in token defines
3909 #endif
3910 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPORT) != DUK_TOK_IMPORT)
3911 #error mismatch in token defines
3912 #endif
3913 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_SUPER) != DUK_TOK_SUPER)
3914 #error mismatch in token defines
3915 #endif
3916 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LC_NULL) != DUK_TOK_NULL)
3917 #error mismatch in token defines
3918 #endif
3919 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_TRUE) != DUK_TOK_TRUE)
3920 #error mismatch in token defines
3921 #endif
3922 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_FALSE) != DUK_TOK_FALSE)
3923 #error mismatch in token defines
3924 #endif
3925 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_IMPLEMENTS) != DUK_TOK_IMPLEMENTS)
3926 #error mismatch in token defines
3927 #endif
3928 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_INTERFACE) != DUK_TOK_INTERFACE)
3929 #error mismatch in token defines
3930 #endif
3931 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_LET) != DUK_TOK_LET)
3932 #error mismatch in token defines
3933 #endif
3934 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PACKAGE) != DUK_TOK_PACKAGE)
3935 #error mismatch in token defines
3936 #endif
3937 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PRIVATE) != DUK_TOK_PRIVATE)
3938 #error mismatch in token defines
3939 #endif
3940 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PROTECTED) != DUK_TOK_PROTECTED)
3941 #error mismatch in token defines
3942 #endif
3943 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_PUBLIC) != DUK_TOK_PUBLIC)
3944 #error mismatch in token defines
3945 #endif
3946 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_STATIC) != DUK_TOK_STATIC)
3947 #error mismatch in token defines
3948 #endif
3949 #if (DUK_STRIDX_TO_TOK(DUK_STRIDX_YIELD) != DUK_TOK_YIELD)
3950 #error mismatch in token defines
3951 #endif
3952 
3953 /* Regexp tokens */
3954 #define DUK_RETOK_EOF                              0
3955 #define DUK_RETOK_DISJUNCTION                      1
3956 #define DUK_RETOK_QUANTIFIER                       2
3957 #define DUK_RETOK_ASSERT_START                     3
3958 #define DUK_RETOK_ASSERT_END                       4
3959 #define DUK_RETOK_ASSERT_WORD_BOUNDARY             5
3960 #define DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY         6
3961 #define DUK_RETOK_ASSERT_START_POS_LOOKAHEAD       7
3962 #define DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD       8
3963 #define DUK_RETOK_ATOM_PERIOD                      9
3964 #define DUK_RETOK_ATOM_CHAR                        10
3965 #define DUK_RETOK_ATOM_DIGIT                       11  /* assumptions in regexp compiler */
3966 #define DUK_RETOK_ATOM_NOT_DIGIT                   12  /* -""- */
3967 #define DUK_RETOK_ATOM_WHITE                       13  /* -""- */
3968 #define DUK_RETOK_ATOM_NOT_WHITE                   14  /* -""- */
3969 #define DUK_RETOK_ATOM_WORD_CHAR                   15  /* -""- */
3970 #define DUK_RETOK_ATOM_NOT_WORD_CHAR               16  /* -""- */
3971 #define DUK_RETOK_ATOM_BACKREFERENCE               17
3972 #define DUK_RETOK_ATOM_START_CAPTURE_GROUP         18
3973 #define DUK_RETOK_ATOM_START_NONCAPTURE_GROUP      19
3974 #define DUK_RETOK_ATOM_START_CHARCLASS             20
3975 #define DUK_RETOK_ATOM_START_CHARCLASS_INVERTED    21
3976 #define DUK_RETOK_ATOM_END_GROUP                   22
3977 
3978 /* Constants for duk_lexer_ctx.buf. */
3979 #define DUK_LEXER_TEMP_BUF_LIMIT                   256
3980 
3981 /* A token value.  Can be memcpy()'d, but note that slot1/slot2 values are on the valstack.
3982  * Some fields (like num, str1, str2) are only valid for specific token types and may have
3983  * stale values otherwise.
3984  */
3985 struct duk_token {
3986 	duk_small_uint_t t;           /* token type (with reserved word identification) */
3987 	duk_small_uint_t t_nores;     /* token type (with reserved words as DUK_TOK_IDENTIFER) */
3988 	duk_double_t num;             /* numeric value of token */
3989 	duk_hstring *str1;            /* string 1 of token (borrowed, stored to ctx->slot1_idx) */
3990 	duk_hstring *str2;            /* string 2 of token (borrowed, stored to ctx->slot2_idx) */
3991 	duk_size_t start_offset;      /* start byte offset of token in lexer input */
3992 	duk_int_t start_line;         /* start line of token (first char) */
3993 	duk_int_t num_escapes;        /* number of escapes and line continuations (for directive prologue) */
3994 	duk_bool_t lineterm;          /* token was preceded by a lineterm */
3995 	duk_bool_t allow_auto_semi;   /* token allows automatic semicolon insertion (eof or preceded by newline) */
3996 };
3997 
3998 #define DUK_RE_QUANTIFIER_INFINITE         ((duk_uint32_t) 0xffffffffUL)
3999 
4000 /* A regexp token value. */
4001 struct duk_re_token {
4002 	duk_small_uint_t t;          /* token type */
4003 	duk_small_uint_t greedy;
4004 	duk_uint32_t num;            /* numeric value (character, count) */
4005 	duk_uint32_t qmin;
4006 	duk_uint32_t qmax;
4007 };
4008 
4009 /* A structure for 'snapshotting' a point for rewinding */
4010 struct duk_lexer_point {
4011 	duk_size_t offset;
4012 	duk_int_t line;
4013 };
4014 
4015 /* Lexer codepoint with additional info like offset/line number */
4016 struct duk_lexer_codepoint {
4017 	duk_codepoint_t codepoint;
4018 	duk_size_t offset;
4019 	duk_int_t line;
4020 };
4021 
4022 /* Lexer context.  Same context is used for ECMAScript and Regexp parsing. */
4023 struct duk_lexer_ctx {
4024 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
4025 	duk_lexer_codepoint *window; /* unicode code points, window[0] is always next, points to 'buffer' */
4026 	duk_lexer_codepoint buffer[DUK_LEXER_BUFFER_SIZE];
4027 #else
4028 	duk_lexer_codepoint window[DUK_LEXER_WINDOW_SIZE]; /* unicode code points, window[0] is always next */
4029 #endif
4030 
4031 	duk_hthread *thr;                              /* thread; minimizes argument passing */
4032 
4033 	const duk_uint8_t *input;                      /* input string (may be a user pointer) */
4034 	duk_size_t input_length;                       /* input byte length */
4035 	duk_size_t input_offset;                       /* input offset for window leading edge (not window[0]) */
4036 	duk_int_t input_line;                          /* input linenumber at input_offset (not window[0]), init to 1 */
4037 
4038 	duk_idx_t slot1_idx;                           /* valstack slot for 1st token value */
4039 	duk_idx_t slot2_idx;                           /* valstack slot for 2nd token value */
4040 	duk_idx_t buf_idx;                             /* valstack slot for temp buffer */
4041 	duk_hbuffer_dynamic *buf;                      /* temp accumulation buffer */
4042 	duk_bufwriter_ctx bw;                          /* bufwriter for temp accumulation */
4043 
4044 	duk_int_t token_count;                         /* number of tokens parsed */
4045 	duk_int_t token_limit;                         /* maximum token count before error (sanity backstop) */
4046 
4047 	duk_small_uint_t flags;                        /* lexer flags, use compiler flag defines for now */
4048 };
4049 
4050 /*
4051  *  Prototypes
4052  */
4053 
4054 DUK_INTERNAL_DECL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx);
4055 
4056 DUK_INTERNAL_DECL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4057 DUK_INTERNAL_DECL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt);
4058 
4059 DUK_INTERNAL_DECL
4060 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
4061                                       duk_token *out_token,
4062                                       duk_bool_t strict_mode,
4063                                       duk_bool_t regexp_mode);
4064 #if defined(DUK_USE_REGEXP_SUPPORT)
4065 DUK_INTERNAL_DECL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token);
4066 DUK_INTERNAL_DECL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata);
4067 #endif  /* DUK_USE_REGEXP_SUPPORT */
4068 
4069 #endif  /* DUK_LEXER_H_INCLUDED */
4070 /* #include duk_js_compiler.h */
4071 #line 1 "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 #line 1 "duk_regexp.h"
4301 /*
4302  *  Regular expression structs, constants, and bytecode defines.
4303  */
4304 
4305 #if !defined(DUK_REGEXP_H_INCLUDED)
4306 #define DUK_REGEXP_H_INCLUDED
4307 
4308 /* maximum bytecode copies for {n,m} quantifiers */
4309 #define DUK_RE_MAX_ATOM_COPIES             1000
4310 
4311 /* regexp compilation limits */
4312 #define DUK_RE_COMPILE_TOKEN_LIMIT         100000000L   /* 1e8 */
4313 
4314 /* regexp execution limits */
4315 #define DUK_RE_EXECUTE_STEPS_LIMIT         1000000000L  /* 1e9 */
4316 
4317 /* regexp opcodes */
4318 #define DUK_REOP_MATCH                     1
4319 #define DUK_REOP_CHAR                      2
4320 #define DUK_REOP_PERIOD                    3
4321 #define DUK_REOP_RANGES                    4
4322 #define DUK_REOP_INVRANGES                 5
4323 #define DUK_REOP_JUMP                      6
4324 #define DUK_REOP_SPLIT1                    7
4325 #define DUK_REOP_SPLIT2                    8
4326 #define DUK_REOP_SQMINIMAL                 9
4327 #define DUK_REOP_SQGREEDY                  10
4328 #define DUK_REOP_SAVE                      11
4329 #define DUK_REOP_WIPERANGE                 12
4330 #define DUK_REOP_LOOKPOS                   13
4331 #define DUK_REOP_LOOKNEG                   14
4332 #define DUK_REOP_BACKREFERENCE             15
4333 #define DUK_REOP_ASSERT_START              16
4334 #define DUK_REOP_ASSERT_END                17
4335 #define DUK_REOP_ASSERT_WORD_BOUNDARY      18
4336 #define DUK_REOP_ASSERT_NOT_WORD_BOUNDARY  19
4337 
4338 /* flags */
4339 #define DUK_RE_FLAG_GLOBAL                 (1U << 0)
4340 #define DUK_RE_FLAG_IGNORE_CASE            (1U << 1)
4341 #define DUK_RE_FLAG_MULTILINE              (1U << 2)
4342 
4343 struct duk_re_matcher_ctx {
4344 	duk_hthread *thr;
4345 
4346 	duk_uint32_t re_flags;
4347 	const duk_uint8_t *input;
4348 	const duk_uint8_t *input_end;
4349 	const duk_uint8_t *bytecode;
4350 	const duk_uint8_t *bytecode_end;
4351 	const duk_uint8_t **saved;  /* allocated from valstack (fixed buffer) */
4352 	duk_uint32_t nsaved;
4353 	duk_uint32_t recursion_depth;
4354 	duk_uint32_t recursion_limit;
4355 	duk_uint32_t steps_count;
4356 	duk_uint32_t steps_limit;
4357 };
4358 
4359 struct duk_re_compiler_ctx {
4360 	duk_hthread *thr;
4361 
4362 	duk_uint32_t re_flags;
4363 	duk_lexer_ctx lex;
4364 	duk_re_token curr_token;
4365 	duk_bufwriter_ctx bw;
4366 	duk_uint32_t captures;  /* highest capture number emitted so far (used as: ++captures) */
4367 	duk_uint32_t highest_backref;
4368 	duk_uint32_t recursion_depth;
4369 	duk_uint32_t recursion_limit;
4370 	duk_uint32_t nranges;  /* internal temporary value, used for char classes */
4371 };
4372 
4373 /*
4374  *  Prototypes
4375  */
4376 
4377 #if defined(DUK_USE_REGEXP_SUPPORT)
4378 DUK_INTERNAL_DECL void duk_regexp_compile(duk_hthread *thr);
4379 DUK_INTERNAL_DECL void duk_regexp_create_instance(duk_hthread *thr);
4380 DUK_INTERNAL_DECL void duk_regexp_match(duk_hthread *thr);
4381 DUK_INTERNAL_DECL void duk_regexp_match_force_global(duk_hthread *thr);  /* hacky helper for String.prototype.split() */
4382 #endif
4383 
4384 #endif  /* DUK_REGEXP_H_INCLUDED */
4385 /* #include duk_heaphdr.h */
4386 #line 1 "duk_heaphdr.h"
4387 /*
4388  *  Heap header definition and assorted macros, including ref counting.
4389  *  Access all fields through the accessor macros.
4390  */
4391 
4392 #if !defined(DUK_HEAPHDR_H_INCLUDED)
4393 #define DUK_HEAPHDR_H_INCLUDED
4394 
4395 /*
4396  *  Common heap header
4397  *
4398  *  All heap objects share the same flags and refcount fields.  Objects other
4399  *  than strings also need to have a single or double linked list pointers
4400  *  for insertion into the "heap allocated" list.  Strings have single linked
4401  *  list pointers for string table chaining.
4402  *
4403  *  Technically, 'h_refcount' must be wide enough to guarantee that it cannot
4404  *  wrap; otherwise objects might be freed incorrectly after wrapping.  The
4405  *  default refcount field is 32 bits even on 64-bit systems: while that's in
4406  *  theory incorrect, the Duktape heap needs to be larger than 64GB for the
4407  *  count to actually wrap (assuming 16-byte duk_tvals).  This is very unlikely
4408  *  to ever be an issue, but if it is, disabling DUK_USE_REFCOUNT32 causes
4409  *  Duktape to use size_t for refcounts which should always be safe.
4410  *
4411  *  Heap header size on 32-bit platforms: 8 bytes without reference counting,
4412  *  16 bytes with reference counting.
4413  *
4414  *  Note that 'raw' macros such as DUK_HEAPHDR_GET_REFCOUNT() are not
4415  *  defined without DUK_USE_REFERENCE_COUNTING, so caller must #if defined()
4416  *  around them.
4417  */
4418 
4419 /* XXX: macro for shared header fields (avoids some padding issues) */
4420 
4421 struct duk_heaphdr {
4422 	duk_uint32_t h_flags;
4423 
4424 #if defined(DUK_USE_REFERENCE_COUNTING)
4425 #if defined(DUK_USE_ASSERTIONS)
4426 	/* When assertions enabled, used by mark-and-sweep for refcount
4427 	 * validation.  Largest reasonable type; also detects overflows.
4428 	 */
4429 	duk_size_t h_assert_refcount;
4430 #endif
4431 #if defined(DUK_USE_REFCOUNT16)
4432 	duk_uint16_t h_refcount;
4433 #elif defined(DUK_USE_REFCOUNT32)
4434 	duk_uint32_t h_refcount;
4435 #else
4436 	duk_size_t h_refcount;
4437 #endif
4438 #endif  /* DUK_USE_REFERENCE_COUNTING */
4439 
4440 #if defined(DUK_USE_HEAPPTR16)
4441 	duk_uint16_t h_next16;
4442 #else
4443 	duk_heaphdr *h_next;
4444 #endif
4445 
4446 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4447 	/* refcounting requires direct heap frees, which in turn requires a dual linked heap */
4448 #if defined(DUK_USE_HEAPPTR16)
4449 	duk_uint16_t h_prev16;
4450 #else
4451 	duk_heaphdr *h_prev;
4452 #endif
4453 #endif
4454 
4455 	/* When DUK_USE_HEAPPTR16 (and DUK_USE_REFCOUNT16) is in use, the
4456 	 * struct won't align nicely to 4 bytes.  This 16-bit extra field
4457 	 * is added to make the alignment clean; the field can be used by
4458 	 * heap objects when 16-bit packing is used.  This field is now
4459 	 * conditional to DUK_USE_HEAPPTR16 only, but it is intended to be
4460 	 * used with DUK_USE_REFCOUNT16 and DUK_USE_DOUBLE_LINKED_HEAP;
4461 	 * this only matter to low memory environments anyway.
4462 	 */
4463 #if defined(DUK_USE_HEAPPTR16)
4464 	duk_uint16_t h_extra16;
4465 #endif
4466 };
4467 
4468 struct duk_heaphdr_string {
4469 	/* 16 bits would be enough for shared heaphdr flags and duk_hstring
4470 	 * flags.  The initial parts of duk_heaphdr_string and duk_heaphdr
4471 	 * must match so changing the flags field size here would be quite
4472 	 * awkward.  However, to minimize struct size, we can pack at least
4473 	 * 16 bits of duk_hstring data into the flags field.
4474 	 */
4475 	duk_uint32_t h_flags;
4476 
4477 #if defined(DUK_USE_REFERENCE_COUNTING)
4478 #if defined(DUK_USE_ASSERTIONS)
4479 	/* When assertions enabled, used by mark-and-sweep for refcount
4480 	 * validation.  Largest reasonable type; also detects overflows.
4481 	 */
4482 	duk_size_t h_assert_refcount;
4483 #endif
4484 #if defined(DUK_USE_REFCOUNT16)
4485 	duk_uint16_t h_refcount;
4486 	duk_uint16_t h_strextra16;  /* round out to 8 bytes */
4487 #elif defined(DUK_USE_REFCOUNT32)
4488 	duk_uint32_t h_refcount;
4489 #else
4490 	duk_size_t h_refcount;
4491 #endif
4492 #else
4493 	duk_uint16_t h_strextra16;
4494 #endif  /* DUK_USE_REFERENCE_COUNTING */
4495 
4496 	duk_hstring *h_next;
4497 	/* No 'h_prev' pointer for strings. */
4498 };
4499 
4500 #define DUK_HEAPHDR_FLAGS_TYPE_MASK      0x00000003UL
4501 #define DUK_HEAPHDR_FLAGS_FLAG_MASK      (~DUK_HEAPHDR_FLAGS_TYPE_MASK)
4502 
4503                                              /* 2 bits for heap type */
4504 #define DUK_HEAPHDR_FLAGS_HEAP_START     2   /* 5 heap flags */
4505 #define DUK_HEAPHDR_FLAGS_USER_START     7   /* 25 user flags */
4506 
4507 #define DUK_HEAPHDR_HEAP_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_HEAP_START + (n))
4508 #define DUK_HEAPHDR_USER_FLAG_NUMBER(n)  (DUK_HEAPHDR_FLAGS_USER_START + (n))
4509 #define DUK_HEAPHDR_HEAP_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_HEAP_START + (n)))
4510 #define DUK_HEAPHDR_USER_FLAG(n)         (1UL << (DUK_HEAPHDR_FLAGS_USER_START + (n)))
4511 
4512 #define DUK_HEAPHDR_FLAG_REACHABLE       DUK_HEAPHDR_HEAP_FLAG(0)  /* mark-and-sweep: reachable */
4513 #define DUK_HEAPHDR_FLAG_TEMPROOT        DUK_HEAPHDR_HEAP_FLAG(1)  /* mark-and-sweep: children not processed */
4514 #define DUK_HEAPHDR_FLAG_FINALIZABLE     DUK_HEAPHDR_HEAP_FLAG(2)  /* mark-and-sweep: finalizable (on current pass) */
4515 #define DUK_HEAPHDR_FLAG_FINALIZED       DUK_HEAPHDR_HEAP_FLAG(3)  /* mark-and-sweep: finalized (on previous pass) */
4516 #define DUK_HEAPHDR_FLAG_READONLY        DUK_HEAPHDR_HEAP_FLAG(4)  /* read-only object, in code section */
4517 
4518 #define DUK_HTYPE_MIN                    0
4519 #define DUK_HTYPE_STRING                 0
4520 #define DUK_HTYPE_OBJECT                 1
4521 #define DUK_HTYPE_BUFFER                 2
4522 #define DUK_HTYPE_MAX                    2
4523 
4524 #if defined(DUK_USE_HEAPPTR16)
4525 #define DUK_HEAPHDR_GET_NEXT(heap,h) \
4526 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_next16))
4527 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4528 		(h)->h_next16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) val); \
4529 	} while (0)
4530 #else
4531 #define DUK_HEAPHDR_GET_NEXT(heap,h)  ((h)->h_next)
4532 #define DUK_HEAPHDR_SET_NEXT(heap,h,val)   do { \
4533 		(h)->h_next = (val); \
4534 	} while (0)
4535 #endif
4536 
4537 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4538 #if defined(DUK_USE_HEAPPTR16)
4539 #define DUK_HEAPHDR_GET_PREV(heap,h) \
4540 	((duk_heaphdr *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->h_prev16))
4541 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4542 		(h)->h_prev16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (val)); \
4543 	} while (0)
4544 #else
4545 #define DUK_HEAPHDR_GET_PREV(heap,h)       ((h)->h_prev)
4546 #define DUK_HEAPHDR_SET_PREV(heap,h,val)   do { \
4547 		(h)->h_prev = (val); \
4548 	} while (0)
4549 #endif
4550 #endif
4551 
4552 #if defined(DUK_USE_REFERENCE_COUNTING)
4553 #define DUK_HEAPHDR_GET_REFCOUNT(h)   ((h)->h_refcount)
4554 #define DUK_HEAPHDR_SET_REFCOUNT(h,val)  do { \
4555 		(h)->h_refcount = (val); \
4556 		DUK_ASSERT((h)->h_refcount == (val));  /* No truncation. */ \
4557 	} while (0)
4558 #define DUK_HEAPHDR_PREINC_REFCOUNT(h)  (++(h)->h_refcount)  /* result: updated refcount */
4559 #define DUK_HEAPHDR_PREDEC_REFCOUNT(h)  (--(h)->h_refcount)  /* result: updated refcount */
4560 #else
4561 /* refcount macros not defined without refcounting, caller must #if defined() now */
4562 #endif  /* DUK_USE_REFERENCE_COUNTING */
4563 
4564 /*
4565  *  Note: type is treated as a field separate from flags, so some masking is
4566  *  involved in the macros below.
4567  */
4568 
4569 #define DUK_HEAPHDR_GET_FLAGS_RAW(h)  ((h)->h_flags)
4570 #define DUK_HEAPHDR_SET_FLAGS_RAW(h,val)  do { \
4571 		(h)->h_flags = (val); } \
4572 	}
4573 #define DUK_HEAPHDR_GET_FLAGS(h)      ((h)->h_flags & DUK_HEAPHDR_FLAGS_FLAG_MASK)
4574 #define DUK_HEAPHDR_SET_FLAGS(h,val)  do { \
4575 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) | (val); \
4576 	} while (0)
4577 #define DUK_HEAPHDR_GET_TYPE(h)       ((h)->h_flags & DUK_HEAPHDR_FLAGS_TYPE_MASK)
4578 #define DUK_HEAPHDR_SET_TYPE(h,val)   do { \
4579 		(h)->h_flags = ((h)->h_flags & ~(DUK_HEAPHDR_FLAGS_TYPE_MASK)) | (val); \
4580 	} while (0)
4581 
4582 /* Comparison for type >= DUK_HTYPE_MIN skipped; because DUK_HTYPE_MIN is zero
4583  * and the comparison is unsigned, it's always true and generates warnings.
4584  */
4585 #define DUK_HEAPHDR_HTYPE_VALID(h)    ( \
4586 	DUK_HEAPHDR_GET_TYPE((h)) <= DUK_HTYPE_MAX \
4587 	)
4588 
4589 #define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h,tval,fval)  do { \
4590 		(h)->h_flags = ((tval) & DUK_HEAPHDR_FLAGS_TYPE_MASK) | \
4591 		               ((fval) & DUK_HEAPHDR_FLAGS_FLAG_MASK); \
4592 	} while (0)
4593 
4594 #define DUK_HEAPHDR_SET_FLAG_BITS(h,bits)  do { \
4595 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4596 		(h)->h_flags |= (bits); \
4597 	} while (0)
4598 
4599 #define DUK_HEAPHDR_CLEAR_FLAG_BITS(h,bits)  do { \
4600 		DUK_ASSERT(((bits) & ~(DUK_HEAPHDR_FLAGS_FLAG_MASK)) == 0); \
4601 		(h)->h_flags &= ~((bits)); \
4602 	} while (0)
4603 
4604 #define DUK_HEAPHDR_CHECK_FLAG_BITS(h,bits)  (((h)->h_flags & (bits)) != 0)
4605 
4606 #define DUK_HEAPHDR_SET_REACHABLE(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4607 #define DUK_HEAPHDR_CLEAR_REACHABLE(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4608 #define DUK_HEAPHDR_HAS_REACHABLE(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_REACHABLE)
4609 
4610 #define DUK_HEAPHDR_SET_TEMPROOT(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4611 #define DUK_HEAPHDR_CLEAR_TEMPROOT(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4612 #define DUK_HEAPHDR_HAS_TEMPROOT(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_TEMPROOT)
4613 
4614 #define DUK_HEAPHDR_SET_FINALIZABLE(h)    DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4615 #define DUK_HEAPHDR_CLEAR_FINALIZABLE(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4616 #define DUK_HEAPHDR_HAS_FINALIZABLE(h)    DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZABLE)
4617 
4618 #define DUK_HEAPHDR_SET_FINALIZED(h)      DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4619 #define DUK_HEAPHDR_CLEAR_FINALIZED(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4620 #define DUK_HEAPHDR_HAS_FINALIZED(h)      DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_FINALIZED)
4621 
4622 #define DUK_HEAPHDR_SET_READONLY(h)       DUK_HEAPHDR_SET_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4623 #define DUK_HEAPHDR_CLEAR_READONLY(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4624 #define DUK_HEAPHDR_HAS_READONLY(h)       DUK_HEAPHDR_CHECK_FLAG_BITS((h),DUK_HEAPHDR_FLAG_READONLY)
4625 
4626 /* get or set a range of flags; m=first bit number, n=number of bits */
4627 #define DUK_HEAPHDR_GET_FLAG_RANGE(h,m,n)  (((h)->h_flags >> (m)) & ((1UL << (n)) - 1UL))
4628 
4629 #define DUK_HEAPHDR_SET_FLAG_RANGE(h,m,n,v)  do { \
4630 		(h)->h_flags = \
4631 			((h)->h_flags & (~(((1UL << (n)) - 1UL) << (m)))) \
4632 			| ((v) << (m)); \
4633 	} while (0)
4634 
4635 /* init pointer fields to null */
4636 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
4637 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4638 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4639 		DUK_HEAPHDR_SET_PREV((h), (void *) NULL); \
4640 	} while (0)
4641 #else
4642 #define DUK_HEAPHDR_INIT_NULLS(h)       do { \
4643 		DUK_HEAPHDR_SET_NEXT((h), (void *) NULL); \
4644 	} while (0)
4645 #endif
4646 
4647 #define DUK_HEAPHDR_STRING_INIT_NULLS(h)  do { \
4648 		(h)->h_next = NULL; \
4649 	} while (0)
4650 
4651 /*
4652  *  Type tests
4653  */
4654 
4655 /* Take advantage of the fact that for DUK_HTYPE_xxx numbers the lowest bit
4656  * is only set for DUK_HTYPE_OBJECT (= 1).
4657  */
4658 #if 0
4659 #define DUK_HEAPHDR_IS_OBJECT(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_OBJECT)
4660 #endif
4661 #define DUK_HEAPHDR_IS_OBJECT(h) ((h)->h_flags & 0x01UL)
4662 #define DUK_HEAPHDR_IS_STRING(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_STRING)
4663 #define DUK_HEAPHDR_IS_BUFFER(h) (DUK_HEAPHDR_GET_TYPE((h)) == DUK_HTYPE_BUFFER)
4664 
4665 /*
4666  *  Assert helpers
4667  */
4668 
4669 /* Check that prev/next links are consistent: if e.g. h->prev is != NULL,
4670  * h->prev->next should point back to h.
4671  */
4672 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_ASSERTIONS)
4673 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do { \
4674 		if ((h) != NULL) { \
4675 			duk_heaphdr *h__prev, *h__next; \
4676 			h__prev = DUK_HEAPHDR_GET_PREV((heap), (h)); \
4677 			h__next = DUK_HEAPHDR_GET_NEXT((heap), (h)); \
4678 			DUK_ASSERT(h__prev == NULL || (DUK_HEAPHDR_GET_NEXT((heap), h__prev) == (h))); \
4679 			DUK_ASSERT(h__next == NULL || (DUK_HEAPHDR_GET_PREV((heap), h__next) == (h))); \
4680 		} \
4681 	} while (0)
4682 #else
4683 #define DUK_ASSERT_HEAPHDR_LINKS(heap,h) do {} while (0)
4684 #endif
4685 
4686 #define DUK_ASSERT_HEAPHDR_VALID(h) do { \
4687 		DUK_ASSERT((h) != NULL); \
4688 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((h))); \
4689 	} while (0)
4690 
4691 #endif  /* DUK_HEAPHDR_H_INCLUDED */
4692 /* #include duk_refcount.h */
4693 #line 1 "duk_refcount.h"
4694 /*
4695  *  Reference counting helper macros.  The macros take a thread argument
4696  *  and must thus always be executed in a specific thread context.  The
4697  *  thread argument is not really needed anymore: DECREF can operate with
4698  *  a heap pointer only, and INCREF needs neither.
4699  */
4700 
4701 #if !defined(DUK_REFCOUNT_H_INCLUDED)
4702 #define DUK_REFCOUNT_H_INCLUDED
4703 
4704 #if defined(DUK_USE_REFERENCE_COUNTING)
4705 
4706 #if defined(DUK_USE_ROM_OBJECTS)
4707 /* With ROM objects "needs refcount update" is true when the value is
4708  * heap allocated and is not a ROM object.
4709  */
4710 /* XXX: double evaluation for 'tv' argument. */
4711 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv) \
4712 	(DUK_TVAL_IS_HEAP_ALLOCATED((tv)) && !DUK_HEAPHDR_HAS_READONLY(DUK_TVAL_GET_HEAPHDR((tv))))
4713 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  (!DUK_HEAPHDR_HAS_READONLY((h)))
4714 #else  /* DUK_USE_ROM_OBJECTS */
4715 /* Without ROM objects "needs refcount update" == is heap allocated. */
4716 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)    DUK_TVAL_IS_HEAP_ALLOCATED((tv))
4717 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)  1
4718 #endif  /* DUK_USE_ROM_OBJECTS */
4719 
4720 /* Fast variants, inline refcount operations except for refzero handling.
4721  * Can be used explicitly when speed is always more important than size.
4722  * For a good compiler and a single file build, these are basically the
4723  * same as a forced inline.
4724  */
4725 #define DUK_TVAL_INCREF_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_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4733 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4734 		} \
4735 	} while (0)
4736 #define DUK_TVAL_DECREF_FAST(thr,tv) do { \
4737 		duk_tval *duk__tv = (tv); \
4738 		DUK_ASSERT(duk__tv != NULL); \
4739 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4740 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4741 			DUK_ASSERT(duk__h != NULL); \
4742 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4743 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4744 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4745 				duk_heaphdr_refzero((thr), duk__h); \
4746 			} \
4747 		} \
4748 	} while (0)
4749 #define DUK_TVAL_DECREF_NORZ_FAST(thr,tv) do { \
4750 		duk_tval *duk__tv = (tv); \
4751 		DUK_ASSERT(duk__tv != NULL); \
4752 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk__tv)) { \
4753 			duk_heaphdr *duk__h = DUK_TVAL_GET_HEAPHDR(duk__tv); \
4754 			DUK_ASSERT(duk__h != NULL); \
4755 			DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4756 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4757 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4758 				duk_heaphdr_refzero_norz((thr), duk__h); \
4759 			} \
4760 		} \
4761 	} while (0)
4762 #define DUK_HEAPHDR_INCREF_FAST(thr,h) do { \
4763 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4764 		DUK_ASSERT(duk__h != NULL); \
4765 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4766 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4767 			DUK_HEAPHDR_PREINC_REFCOUNT(duk__h); \
4768 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) != 0);  /* No wrapping. */ \
4769 		} \
4770 	} while (0)
4771 #define DUK_HEAPHDR_DECREF_FAST_RAW(thr,h,rzcall,rzcast) do { \
4772 		duk_heaphdr *duk__h = (duk_heaphdr *) (h); \
4773 		DUK_ASSERT(duk__h != NULL); \
4774 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(duk__h)); \
4775 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(duk__h) > 0); \
4776 		if (DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(duk__h)) { \
4777 			if (DUK_HEAPHDR_PREDEC_REFCOUNT(duk__h) == 0) { \
4778 				(rzcall)((thr), (rzcast) duk__h); \
4779 			} \
4780 		} \
4781 	} while (0)
4782 #define DUK_HEAPHDR_DECREF_FAST(thr,h) \
4783 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4784 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h) \
4785 	DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4786 
4787 /* Slow variants, call to a helper to reduce code size.
4788  * Can be used explicitly when size is always more important than speed.
4789  */
4790 #define DUK_TVAL_INCREF_SLOW(thr,tv)         do { duk_tval_incref((tv)); } while (0)
4791 #define DUK_TVAL_DECREF_SLOW(thr,tv)         do { duk_tval_decref((thr), (tv)); } while (0)
4792 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,tv)    do { duk_tval_decref_norz((thr), (tv)); } while (0)
4793 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4794 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4795 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4796 #define DUK_HSTRING_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4797 #define DUK_HSTRING_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4798 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4799 #define DUK_HBUFFER_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4800 #define DUK_HBUFFER_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4801 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4802 #define DUK_HOBJECT_INCREF_SLOW(thr,h)       do { duk_heaphdr_incref((duk_heaphdr *) (h)); } while (0)
4803 #define DUK_HOBJECT_DECREF_SLOW(thr,h)       do { duk_heaphdr_decref((thr), (duk_heaphdr *) (h)); } while (0)
4804 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)  do { duk_heaphdr_decref_norz((thr), (duk_heaphdr *) (h)); } while (0)
4805 
4806 /* Default variants.  Selection depends on speed/size preference.
4807  * Concretely: with gcc 4.8.1 -Os x64 the difference in final binary
4808  * is about +1kB for _FAST variants.
4809  */
4810 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
4811 /* XXX: It would be nice to specialize for specific duk_hobject subtypes
4812  * but current refzero queue handling prevents that.
4813  */
4814 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_FAST((thr),(tv))
4815 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_FAST((thr),(tv))
4816 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_FAST((thr),(tv))
4817 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_FAST((thr),(h))
4818 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero,duk_heaphdr *)
4819 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_heaphdr_refzero_norz,duk_heaphdr *)
4820 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4821 #define DUK_HSTRING_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)
4822 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hstring_refzero,duk_hstring *)  /* no 'norz' variant */
4823 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4824 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4825 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4826 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4827 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)
4828 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hbuffer_refzero,duk_hbuffer *)  /* no 'norz' variant */
4829 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4830 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4831 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4832 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4833 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4834 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4835 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4836 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4837 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4838 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4839 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero,duk_hobject *)
4840 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_FAST_RAW((thr),(h),duk_hobject_refzero_norz,duk_hobject *)
4841 #else
4842 #define DUK_TVAL_INCREF(thr,tv)                DUK_TVAL_INCREF_SLOW((thr),(tv))
4843 #define DUK_TVAL_DECREF(thr,tv)                DUK_TVAL_DECREF_SLOW((thr),(tv))
4844 #define DUK_TVAL_DECREF_NORZ(thr,tv)           DUK_TVAL_DECREF_NORZ_SLOW((thr),(tv))
4845 #define DUK_HEAPHDR_INCREF(thr,h)              DUK_HEAPHDR_INCREF_SLOW((thr),(h))
4846 #define DUK_HEAPHDR_DECREF(thr,h)              DUK_HEAPHDR_DECREF_SLOW((thr),(h))
4847 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         DUK_HEAPHDR_DECREF_NORZ_SLOW((thr),(h))
4848 #define DUK_HSTRING_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4849 #define DUK_HSTRING_DECREF(thr,h)              DUK_HSTRING_DECREF_SLOW((thr),(h))
4850 #define DUK_HSTRING_DECREF_NORZ(thr,h)         DUK_HSTRING_DECREF_NORZ_SLOW((thr),(h))
4851 #define DUK_HOBJECT_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4852 #define DUK_HOBJECT_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(h))
4853 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(h))
4854 #define DUK_HBUFFER_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) (h))
4855 #define DUK_HBUFFER_DECREF(thr,h)              DUK_HBUFFER_DECREF_SLOW((thr),(h))
4856 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         DUK_HBUFFER_DECREF_NORZ_SLOW((thr),(h))
4857 #define DUK_HCOMPFUNC_INCREF(thr,h)            DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4858 #define DUK_HCOMPFUNC_DECREF(thr,h)            DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4859 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4860 #define DUK_HNATFUNC_INCREF(thr,h)             DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4861 #define DUK_HNATFUNC_DECREF(thr,h)             DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4862 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4863 #define DUK_HBUFOBJ_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4864 #define DUK_HBUFOBJ_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4865 #define DUK_HBUFOB_DECREF_NORZ(thr,h)          DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4866 #define DUK_HTHREAD_INCREF(thr,h)              DUK_HEAPHDR_INCREF((thr),(duk_heaphdr *) &(h)->obj)
4867 #define DUK_HTHREAD_DECREF(thr,h)              DUK_HOBJECT_DECREF_SLOW((thr),(duk_hobject *) &(h)->obj)
4868 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         DUK_HOBJECT_DECREF_NORZ_SLOW((thr),(duk_hobject *) &(h)->obj)
4869 #endif
4870 
4871 /* Convenience for some situations; the above macros don't allow NULLs
4872  * for performance reasons.  Macros cover only actually needed cases.
4873  */
4874 #define DUK_HEAPHDR_INCREF_ALLOWNULL(thr,h) do { \
4875 		if ((h) != NULL) { \
4876 			DUK_HEAPHDR_INCREF((thr), (duk_heaphdr *) (h)); \
4877 		} \
4878 	} while (0)
4879 #define DUK_HEAPHDR_DECREF_ALLOWNULL(thr,h) do { \
4880 		if ((h) != NULL) { \
4881 			DUK_HEAPHDR_DECREF((thr), (duk_heaphdr *) (h)); \
4882 		} \
4883 	} while (0)
4884 #define DUK_HEAPHDR_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4885 		if ((h) != NULL) { \
4886 			DUK_HEAPHDR_DECREF_NORZ((thr), (duk_heaphdr *) (h)); \
4887 		} \
4888 	} while (0)
4889 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h) do { \
4890 		if ((h) != NULL) { \
4891 			DUK_HOBJECT_INCREF((thr), (h)); \
4892 		} \
4893 	} while (0)
4894 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h) do { \
4895 		if ((h) != NULL) { \
4896 			DUK_HOBJECT_DECREF((thr), (h)); \
4897 		} \
4898 	} while (0)
4899 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4900 		if ((h) != NULL) { \
4901 			DUK_HOBJECT_DECREF_NORZ((thr), (h)); \
4902 		} \
4903 	} while (0)
4904 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h) do { \
4905 		if ((h) != NULL) { \
4906 			DUK_HBUFFER_INCREF((thr), (h)); \
4907 		} \
4908 	} while (0)
4909 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h) do { \
4910 		if ((h) != NULL) { \
4911 			DUK_HBUFFER_DECREF((thr), (h)); \
4912 		} \
4913 	} while (0)
4914 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4915 		if ((h) != NULL) { \
4916 			DUK_HBUFFER_DECREF_NORZ((thr), (h)); \
4917 		} \
4918 	} while (0)
4919 #define DUK_HTHREAD_INCREF_ALLOWNULL(thr,h) do { \
4920 		if ((h) != NULL) { \
4921 			DUK_HTHREAD_INCREF((thr), (h)); \
4922 		} \
4923 	} while (0)
4924 #define DUK_HTHREAD_DECREF_ALLOWNULL(thr,h) do { \
4925 		if ((h) != NULL) { \
4926 			DUK_HTHREAD_DECREF((thr), (h)); \
4927 		} \
4928 	} while (0)
4929 #define DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr,h) do { \
4930 		if ((h) != NULL) { \
4931 			DUK_HTHREAD_DECREF_NORZ((thr), (h)); \
4932 		} \
4933 	} while (0)
4934 
4935 /* Called after one or more DECREF NORZ calls to handle pending side effects.
4936  * At present DECREF NORZ does freeing inline but doesn't execute finalizers,
4937  * so these macros check for pending finalizers and execute them.  The FAST
4938  * variant is performance critical.
4939  */
4940 #if defined(DUK_USE_FINALIZER_SUPPORT)
4941 #define DUK_REFZERO_CHECK_FAST(thr) do { \
4942 		duk_refzero_check_fast((thr)); \
4943 	} while (0)
4944 #define DUK_REFZERO_CHECK_SLOW(thr) do { \
4945 		duk_refzero_check_slow((thr)); \
4946 	} while (0)
4947 #else  /* DUK_USE_FINALIZER_SUPPORT */
4948 #define DUK_REFZERO_CHECK_FAST(thr) do { } while (0)
4949 #define DUK_REFZERO_CHECK_SLOW(thr) do { } while (0)
4950 #endif  /* DUK_USE_FINALIZER_SUPPORT */
4951 
4952 /*
4953  *  Macros to set a duk_tval and update refcount of the target (decref the
4954  *  old value and incref the new value if necessary).  This is both performance
4955  *  and footprint critical; any changes made should be measured for size/speed.
4956  */
4957 
4958 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
4959 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4960 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4961 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4962 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4963 	} while (0)
4964 
4965 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0(thr,tvptr_dst) do { \
4966 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4967 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4968 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
4969 		DUK_TVAL_DECREF_NORZ((thr), &tv__tmp); \
4970 	} while (0)
4971 
4972 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
4973 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4974 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4975 		DUK_TVAL_SET_UNUSED(tv__dst); \
4976 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4977 	} while (0)
4978 
4979 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
4980 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4981 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4982 		DUK_TVAL_SET_NULL(tv__dst); \
4983 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4984 	} while (0)
4985 
4986 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4987 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4988 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4989 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
4990 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4991 	} while (0)
4992 
4993 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
4994 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
4995 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
4996 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
4997 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
4998 	} while (0)
4999 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5000 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5001 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5002 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5003 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5004 	} while (0)
5005 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5006 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5007 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5008 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5009 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5010 	} while (0)
5011 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5012 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5013 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5014 		DUK_TVAL_SET_NAN(tv__dst); \
5015 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5016 	} while (0)
5017 #if defined(DUK_USE_FASTINT)
5018 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5019 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5020 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5021 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5022 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5023 	} while (0)
5024 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5025 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5026 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5027 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5028 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5029 	} while (0)
5030 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) 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_U32(tv__dst, (newval)); \
5034 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5035 	} while (0)
5036 #else
5037 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5038 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5039 #endif  /* DUK_USE_FASTINT */
5040 
5041 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5042 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5043 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5044 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5045 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5046 	} while (0)
5047 
5048 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5049 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5050 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5051 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5052 		DUK_HSTRING_INCREF((thr), (newval)); \
5053 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5054 	} while (0)
5055 
5056 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5057 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5058 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5059 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5060 		DUK_HOBJECT_INCREF((thr), (newval)); \
5061 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5062 	} while (0)
5063 
5064 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5065 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5066 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5067 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5068 		DUK_HBUFFER_INCREF((thr), (newval)); \
5069 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5070 	} while (0)
5071 
5072 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5073 		duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
5074 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5075 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5076 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5077 	} while (0)
5078 
5079 /* DUK_TVAL_SET_TVAL_UPDREF() is used a lot in executor, property lookups,
5080  * etc, so it's very important for performance.  Measure when changing.
5081  *
5082  * NOTE: the source and destination duk_tval pointers may be the same, and
5083  * the macros MUST deal with that correctly.
5084  */
5085 
5086 /* Original idiom used, minimal code size. */
5087 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5088 		duk_tval *tv__dst, *tv__src; duk_tval tv__tmp; \
5089 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5090 		DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
5091 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5092 		DUK_TVAL_INCREF((thr), tv__src); \
5093 		DUK_TVAL_DECREF((thr), &tv__tmp);  /* side effects */ \
5094 	} while (0)
5095 
5096 /* Faster alternative: avoid making a temporary copy of tvptr_dst and use
5097  * fast incref/decref macros.
5098  */
5099 #define DUK_TVAL_SET_TVAL_UPDREF_ALT1(thr,tvptr_dst,tvptr_src) do { \
5100 		duk_tval *tv__dst, *tv__src; duk_heaphdr *h__obj; \
5101 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5102 		DUK_TVAL_INCREF_FAST((thr), tv__src); \
5103 		if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv__dst)) { \
5104 			h__obj = DUK_TVAL_GET_HEAPHDR(tv__dst); \
5105 			DUK_ASSERT(h__obj != NULL); \
5106 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5107 			DUK_HEAPHDR_DECREF_FAST((thr), h__obj);  /* side effects */ \
5108 		} else { \
5109 			DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5110 		} \
5111 	} while (0)
5112 
5113 /* XXX: no optimized variants yet */
5114 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5115 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ_ALT0
5116 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5117 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5118 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5119 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5120 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5121 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5122 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5123 #if defined(DUK_USE_FASTINT)
5124 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5125 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5126 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5127 #else
5128 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast int-to-double */
5129 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5130 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5131 #endif  /* DUK_USE_FASTINT */
5132 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5133 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5134 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5135 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5136 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5137 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5138 
5139 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5140 /* Optimized for speed. */
5141 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT1
5142 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT1
5143 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5144 #else
5145 /* Optimized for size. */
5146 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5147 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5148 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5149 #endif
5150 
5151 #else  /* DUK_USE_REFERENCE_COUNTING */
5152 
5153 #define DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)     0
5154 #define DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE(h)   0
5155 
5156 #define DUK_TVAL_INCREF_FAST(thr,v)            do {} while (0) /* nop */
5157 #define DUK_TVAL_DECREF_FAST(thr,v)            do {} while (0) /* nop */
5158 #define DUK_TVAL_DECREF_NORZ_FAST(thr,v)       do {} while (0) /* nop */
5159 #define DUK_TVAL_INCREF_SLOW(thr,v)            do {} while (0) /* nop */
5160 #define DUK_TVAL_DECREF_SLOW(thr,v)            do {} while (0) /* nop */
5161 #define DUK_TVAL_DECREF_NORZ_SLOW(thr,v)       do {} while (0) /* nop */
5162 #define DUK_TVAL_INCREF(thr,v)                 do {} while (0) /* nop */
5163 #define DUK_TVAL_DECREF(thr,v)                 do {} while (0) /* nop */
5164 #define DUK_TVAL_DECREF_NORZ(thr,v)            do {} while (0) /* nop */
5165 #define DUK_HEAPHDR_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5166 #define DUK_HEAPHDR_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5167 #define DUK_HEAPHDR_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5168 #define DUK_HEAPHDR_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5169 #define DUK_HEAPHDR_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5170 #define DUK_HEAPHDR_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5171 #define DUK_HEAPHDR_INCREF(thr,h)              do {} while (0) /* nop */
5172 #define DUK_HEAPHDR_DECREF(thr,h)              do {} while (0) /* nop */
5173 #define DUK_HEAPHDR_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5174 #define DUK_HSTRING_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5175 #define DUK_HSTRING_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5176 #define DUK_HSTRING_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5177 #define DUK_HSTRING_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5178 #define DUK_HSTRING_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5179 #define DUK_HSTRING_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5180 #define DUK_HSTRING_INCREF(thr,h)              do {} while (0) /* nop */
5181 #define DUK_HSTRING_DECREF(thr,h)              do {} while (0) /* nop */
5182 #define DUK_HSTRING_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5183 #define DUK_HOBJECT_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5184 #define DUK_HOBJECT_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5185 #define DUK_HOBJECT_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5186 #define DUK_HOBJECT_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5187 #define DUK_HOBJECT_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5188 #define DUK_HOBJECT_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5189 #define DUK_HOBJECT_INCREF(thr,h)              do {} while (0) /* nop */
5190 #define DUK_HOBJECT_DECREF(thr,h)              do {} while (0) /* nop */
5191 #define DUK_HOBJECT_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5192 #define DUK_HBUFFER_INCREF_FAST(thr,h)         do {} while (0) /* nop */
5193 #define DUK_HBUFFER_DECREF_FAST(thr,h)         do {} while (0) /* nop */
5194 #define DUK_HBUFFER_DECREF_NORZ_FAST(thr,h)    do {} while (0) /* nop */
5195 #define DUK_HBUFFER_INCREF_SLOW(thr,h)         do {} while (0) /* nop */
5196 #define DUK_HBUFFER_DECREF_SLOW(thr,h)         do {} while (0) /* nop */
5197 #define DUK_HBUFFER_DECREF_NORZ_SLOW(thr,h)    do {} while (0) /* nop */
5198 #define DUK_HBUFFER_INCREF(thr,h)              do {} while (0) /* nop */
5199 #define DUK_HBUFFER_DECREF(thr,h)              do {} while (0) /* nop */
5200 #define DUK_HBUFFER_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5201 
5202 #define DUK_HCOMPFUNC_INCREF(thr,h)            do {} while (0) /* nop */
5203 #define DUK_HCOMPFUNC_DECREF(thr,h)            do {} while (0) /* nop */
5204 #define DUK_HCOMPFUNC_DECREF_NORZ(thr,h)       do {} while (0) /* nop */
5205 #define DUK_HNATFUNC_INCREF(thr,h)             do {} while (0) /* nop */
5206 #define DUK_HNATFUNC_DECREF(thr,h)             do {} while (0) /* nop */
5207 #define DUK_HNATFUNC_DECREF_NORZ(thr,h)        do {} while (0) /* nop */
5208 #define DUK_HBUFOBJ_INCREF(thr,h)              do {} while (0) /* nop */
5209 #define DUK_HBUFOBJ_DECREF(thr,h)              do {} while (0) /* nop */
5210 #define DUK_HBUFOBJ_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5211 #define DUK_HTHREAD_INCREF(thr,h)              do {} while (0) /* nop */
5212 #define DUK_HTHREAD_DECREF(thr,h)              do {} while (0) /* nop */
5213 #define DUK_HTHREAD_DECREF_NORZ(thr,h)         do {} while (0) /* nop */
5214 #define DUK_HOBJECT_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5215 #define DUK_HOBJECT_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5216 #define DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5217 #define DUK_HBUFFER_INCREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5218 #define DUK_HBUFFER_DECREF_ALLOWNULL(thr,h)    do {} while (0) /* nop */
5219 #define DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr,h)  do {} while (0) /* nop */
5220 
5221 #define DUK_REFZERO_CHECK_FAST(thr)            do {} while (0) /* nop */
5222 #define DUK_REFZERO_CHECK_SLOW(thr)            do {} while (0) /* nop */
5223 
5224 #define DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0(thr,tvptr_dst) do { \
5225 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5226 		DUK_TVAL_SET_UNDEFINED(tv__dst); \
5227 		DUK_UNREF((thr)); \
5228 	} while (0)
5229 
5230 #define DUK_TVAL_SET_UNUSED_UPDREF_ALT0(thr,tvptr_dst) do { \
5231 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5232 		DUK_TVAL_SET_UNUSED(tv__dst); \
5233 		DUK_UNREF((thr)); \
5234 	} while (0)
5235 
5236 #define DUK_TVAL_SET_NULL_UPDREF_ALT0(thr,tvptr_dst) do { \
5237 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5238 		DUK_TVAL_SET_NULL(tv__dst); \
5239 		DUK_UNREF((thr)); \
5240 	} while (0)
5241 
5242 #define DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5243 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5244 		DUK_TVAL_SET_BOOLEAN(tv__dst, (newval)); \
5245 		DUK_UNREF((thr)); \
5246 	} while (0)
5247 
5248 #define DUK_TVAL_SET_NUMBER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5249 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5250 		DUK_TVAL_SET_NUMBER(tv__dst, (newval)); \
5251 		DUK_UNREF((thr)); \
5252 	} while (0)
5253 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5254 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5255 		DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
5256 		DUK_UNREF((thr)); \
5257 	} while (0)
5258 #define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5259 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5260 		DUK_TVAL_SET_DOUBLE(tv__dst, (newval)); \
5261 		DUK_UNREF((thr)); \
5262 	} while (0)
5263 #define DUK_TVAL_SET_NAN_UPDREF_ALT0(thr,tvptr_dst) do { \
5264 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5265 		DUK_TVAL_SET_NAN(tv__dst); \
5266 		DUK_UNREF((thr)); \
5267 	} while (0)
5268 #if defined(DUK_USE_FASTINT)
5269 #define DUK_TVAL_SET_I48_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5270 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5271 		DUK_TVAL_SET_I48(tv__dst, (newval)); \
5272 		DUK_UNREF((thr)); \
5273 	} while (0)
5274 #define DUK_TVAL_SET_I32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5275 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5276 		DUK_TVAL_SET_I32(tv__dst, (newval)); \
5277 		DUK_UNREF((thr)); \
5278 	} while (0)
5279 #define DUK_TVAL_SET_U32_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5280 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5281 		DUK_TVAL_SET_U32(tv__dst, (newval)); \
5282 		DUK_UNREF((thr)); \
5283 	} while (0)
5284 #else
5285 #define DUK_TVAL_SET_DOUBLE_CAST_UPDREF(thr,tvptr_dst,newval) \
5286 	DUK_TVAL_SET_DOUBLE_UPDREF((thr), (tvptr_dst), (duk_double_t) (newval))
5287 #endif  /* DUK_USE_FASTINT */
5288 
5289 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0(thr,tvptr_dst,lf_v,lf_fp,lf_flags) do { \
5290 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5291 		DUK_TVAL_SET_LIGHTFUNC(tv__dst, (lf_v), (lf_fp), (lf_flags)); \
5292 		DUK_UNREF((thr)); \
5293 	} while (0)
5294 
5295 #define DUK_TVAL_SET_STRING_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5296 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5297 		DUK_TVAL_SET_STRING(tv__dst, (newval)); \
5298 		DUK_UNREF((thr)); \
5299 	} while (0)
5300 
5301 #define DUK_TVAL_SET_OBJECT_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5302 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5303 		DUK_TVAL_SET_OBJECT(tv__dst, (newval)); \
5304 		DUK_UNREF((thr)); \
5305 	} while (0)
5306 
5307 #define DUK_TVAL_SET_BUFFER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5308 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5309 		DUK_TVAL_SET_BUFFER(tv__dst, (newval)); \
5310 		DUK_UNREF((thr)); \
5311 	} while (0)
5312 
5313 #define DUK_TVAL_SET_POINTER_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
5314 		duk_tval *tv__dst; tv__dst = (tvptr_dst); \
5315 		DUK_TVAL_SET_POINTER(tv__dst, (newval)); \
5316 		DUK_UNREF((thr)); \
5317 	} while (0)
5318 
5319 #define DUK_TVAL_SET_TVAL_UPDREF_ALT0(thr,tvptr_dst,tvptr_src) do { \
5320 		duk_tval *tv__dst, *tv__src; \
5321 		tv__dst = (tvptr_dst); tv__src = (tvptr_src); \
5322 		DUK_TVAL_SET_TVAL(tv__dst, tv__src); \
5323 		DUK_UNREF((thr)); \
5324 	} while (0)
5325 
5326 #define DUK_TVAL_SET_UNDEFINED_UPDREF         DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5327 #define DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ    DUK_TVAL_SET_UNDEFINED_UPDREF_ALT0
5328 #define DUK_TVAL_SET_UNUSED_UPDREF            DUK_TVAL_SET_UNUSED_UPDREF_ALT0
5329 #define DUK_TVAL_SET_NULL_UPDREF              DUK_TVAL_SET_NULL_UPDREF_ALT0
5330 #define DUK_TVAL_SET_BOOLEAN_UPDREF           DUK_TVAL_SET_BOOLEAN_UPDREF_ALT0
5331 #define DUK_TVAL_SET_NUMBER_UPDREF            DUK_TVAL_SET_NUMBER_UPDREF_ALT0
5332 #define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF    DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0
5333 #define DUK_TVAL_SET_DOUBLE_UPDREF            DUK_TVAL_SET_DOUBLE_UPDREF_ALT0
5334 #define DUK_TVAL_SET_NAN_UPDREF               DUK_TVAL_SET_NAN_UPDREF_ALT0
5335 #if defined(DUK_USE_FASTINT)
5336 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_I48_UPDREF_ALT0
5337 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_I32_UPDREF_ALT0
5338 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_U32_UPDREF_ALT0
5339 #else
5340 #define DUK_TVAL_SET_I48_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF  /* XXX: fast-int-to-double */
5341 #define DUK_TVAL_SET_I32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5342 #define DUK_TVAL_SET_U32_UPDREF               DUK_TVAL_SET_DOUBLE_CAST_UPDREF
5343 #endif  /* DUK_USE_FASTINT */
5344 #define DUK_TVAL_SET_FASTINT_UPDREF           DUK_TVAL_SET_I48_UPDREF  /* convenience */
5345 #define DUK_TVAL_SET_LIGHTFUNC_UPDREF         DUK_TVAL_SET_LIGHTFUNC_UPDREF_ALT0
5346 #define DUK_TVAL_SET_STRING_UPDREF            DUK_TVAL_SET_STRING_UPDREF_ALT0
5347 #define DUK_TVAL_SET_OBJECT_UPDREF            DUK_TVAL_SET_OBJECT_UPDREF_ALT0
5348 #define DUK_TVAL_SET_BUFFER_UPDREF            DUK_TVAL_SET_BUFFER_UPDREF_ALT0
5349 #define DUK_TVAL_SET_POINTER_UPDREF           DUK_TVAL_SET_POINTER_UPDREF_ALT0
5350 
5351 #define DUK_TVAL_SET_TVAL_UPDREF              DUK_TVAL_SET_TVAL_UPDREF_ALT0
5352 #define DUK_TVAL_SET_TVAL_UPDREF_FAST         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5353 #define DUK_TVAL_SET_TVAL_UPDREF_SLOW         DUK_TVAL_SET_TVAL_UPDREF_ALT0
5354 
5355 #endif  /* DUK_USE_REFERENCE_COUNTING */
5356 
5357 /*
5358  *  Some convenience macros that don't have optimized implementations now.
5359  */
5360 
5361 #define DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr,tv_dst,tv_src) do { \
5362 		duk_hthread *duk__thr = (thr); \
5363 		duk_tval *duk__dst = (tv_dst); \
5364 		duk_tval *duk__src = (tv_src); \
5365 		DUK_UNREF(duk__thr); \
5366 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5367 		DUK_TVAL_SET_TVAL(duk__dst, duk__src); \
5368 		DUK_TVAL_INCREF(thr, duk__dst); \
5369 	} while (0)
5370 
5371 #define DUK_TVAL_SET_U32_UPDREF_NORZ(thr,tv_dst,val) do { \
5372 		duk_hthread *duk__thr = (thr); \
5373 		duk_tval *duk__dst = (tv_dst); \
5374 		duk_uint32_t duk__val = (duk_uint32_t) (val); \
5375 		DUK_UNREF(duk__thr); \
5376 		DUK_TVAL_DECREF_NORZ(thr, duk__dst); \
5377 		DUK_TVAL_SET_U32(duk__dst, duk__val); \
5378 	} while (0)
5379 
5380 /*
5381  *  Prototypes
5382  */
5383 
5384 #if defined(DUK_USE_REFERENCE_COUNTING)
5385 #if defined(DUK_USE_FINALIZER_SUPPORT)
5386 DUK_INTERNAL_DECL void duk_refzero_check_slow(duk_hthread *thr);
5387 DUK_INTERNAL_DECL void duk_refzero_check_fast(duk_hthread *thr);
5388 #endif
5389 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr);
5390 DUK_INTERNAL_DECL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h);
5391 #if 0  /* Not needed: fast path handles inline; slow path uses duk_heaphdr_decref() which is needed anyway. */
5392 DUK_INTERNAL_DECL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h);
5393 DUK_INTERNAL_DECL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h);
5394 DUK_INTERNAL_DECL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h);
5395 DUK_INTERNAL_DECL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h);
5396 DUK_INTERNAL_DECL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h);
5397 DUK_INTERNAL_DECL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h);
5398 #endif
5399 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h);
5400 DUK_INTERNAL_DECL void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h);
5401 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
5402 DUK_INTERNAL_DECL void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h);  /* no 'norz' variant */
5403 DUK_INTERNAL_DECL void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h);  /* no 'norz' variant */
5404 DUK_INTERNAL_DECL void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h);
5405 DUK_INTERNAL_DECL void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h);
5406 #else
5407 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv);
5408 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv);
5409 DUK_INTERNAL_DECL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv);
5410 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h);
5411 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h);
5412 DUK_INTERNAL_DECL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h);
5413 #endif
5414 #else  /* DUK_USE_REFERENCE_COUNTING */
5415 /* no refcounting */
5416 #endif  /* DUK_USE_REFERENCE_COUNTING */
5417 
5418 #endif  /* DUK_REFCOUNT_H_INCLUDED */
5419 /* #include duk_api_internal.h */
5420 #line 1 "duk_api_internal.h"
5421 /*
5422  *  Internal API calls which have (stack and other) semantics similar
5423  *  to the public API.
5424  */
5425 
5426 #if !defined(DUK_API_INTERNAL_H_INCLUDED)
5427 #define DUK_API_INTERNAL_H_INCLUDED
5428 
5429 #define DUK_INTERNAL_SYMBOL(x)     ("\x82" x)
5430 
5431 /* duk_push_sprintf constants */
5432 #define DUK_PUSH_SPRINTF_INITIAL_SIZE  256L
5433 #define DUK_PUSH_SPRINTF_SANITY_LIMIT  (1L * 1024L * 1024L * 1024L)
5434 
5435 /* Flag ORed to err_code to indicate __FILE__ / __LINE__ is not
5436  * blamed as source of error for error fileName / lineNumber.
5437  */
5438 #define DUK_ERRCODE_FLAG_NOBLAME_FILELINE  (1L << 24)
5439 
5440 /* Current convention is to use duk_size_t for value stack sizes and global indices,
5441  * and duk_idx_t for local frame indices.
5442  */
5443 DUK_INTERNAL_DECL void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes);
5444 DUK_INTERNAL_DECL duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes);
5445 DUK_INTERNAL_DECL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug);
5446 
5447 DUK_INTERNAL_DECL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count);
5448 
5449 DUK_INTERNAL_DECL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count);
5450 
5451 DUK_INTERNAL_DECL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx);
5452 DUK_INTERNAL_DECL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start);
5453 
5454 DUK_INTERNAL_DECL void duk_dup_0(duk_hthread *thr);
5455 DUK_INTERNAL_DECL void duk_dup_1(duk_hthread *thr);
5456 DUK_INTERNAL_DECL void duk_dup_2(duk_hthread *thr);
5457 /* duk_dup_m1() would be same as duk_dup_top() */
5458 DUK_INTERNAL_DECL void duk_dup_m2(duk_hthread *thr);
5459 DUK_INTERNAL_DECL void duk_dup_m3(duk_hthread *thr);
5460 DUK_INTERNAL_DECL void duk_dup_m4(duk_hthread *thr);
5461 
5462 DUK_INTERNAL_DECL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx);
5463 DUK_INTERNAL_DECL void duk_remove_m2(duk_hthread *thr);
5464 DUK_INTERNAL_DECL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5465 DUK_INTERNAL_DECL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5466 
5467 DUK_INTERNAL_DECL duk_int_t duk_get_type_tval(duk_tval *tv);
5468 DUK_INTERNAL_DECL duk_uint_t duk_get_type_mask_tval(duk_tval *tv);
5469 
5470 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
5471 DUK_INTERNAL_DECL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx);
5472 #endif
5473 DUK_INTERNAL_DECL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx);
5474 
5475 DUK_INTERNAL_DECL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx);
5476 DUK_INTERNAL_DECL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx);
5477 DUK_INTERNAL_DECL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx);
5478 DUK_INTERNAL_DECL void duk_push_tval(duk_hthread *thr, duk_tval *tv);
5479 
5480 /* Push the current 'this' binding; throw TypeError if binding is not object
5481  * coercible (CheckObjectCoercible).
5482  */
5483 DUK_INTERNAL_DECL void duk_push_this_check_object_coercible(duk_hthread *thr);
5484 
5485 /* duk_push_this() + CheckObjectCoercible() + duk_to_object() */
5486 DUK_INTERNAL_DECL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr);
5487 
5488 /* duk_push_this() + CheckObjectCoercible() + duk_to_string() */
5489 DUK_INTERNAL_DECL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr);
5490 
5491 DUK_INTERNAL_DECL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i);
5492 
5493 /* Get a borrowed duk_tval pointer to the current 'this' binding.  Caller must
5494  * make sure there's an active callstack entry.  Note that the returned pointer
5495  * is unstable with regards to side effects.
5496  */
5497 DUK_INTERNAL_DECL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr);
5498 
5499 /* XXX: add fastint support? */
5500 #define duk_push_u64(thr,val) \
5501 	duk_push_number((thr), (duk_double_t) (val))
5502 #define duk_push_i64(thr,val) \
5503 	duk_push_number((thr), (duk_double_t) (val))
5504 
5505 /* duk_push_(u)int() is guaranteed to support at least (un)signed 32-bit range */
5506 #define duk_push_u32(thr,val) \
5507 	duk_push_uint((thr), (duk_uint_t) (val))
5508 #define duk_push_i32(thr,val) \
5509 	duk_push_int((thr), (duk_int_t) (val))
5510 
5511 /* sometimes stack and array indices need to go on the stack */
5512 #define duk_push_idx(thr,val) \
5513 	duk_push_int((thr), (duk_int_t) (val))
5514 #define duk_push_uarridx(thr,val) \
5515 	duk_push_uint((thr), (duk_uint_t) (val))
5516 #define duk_push_size_t(thr,val) \
5517 	duk_push_uint((thr), (duk_uint_t) (val))  /* XXX: assumed to fit for now */
5518 
5519 DUK_INTERNAL_DECL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5520 
5521 DUK_INTERNAL_DECL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv);
5522 
5523 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx);
5524 DUK_INTERNAL_DECL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5525 DUK_INTERNAL_DECL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5526 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx);
5527 DUK_INTERNAL_DECL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx);
5528 DUK_INTERNAL_DECL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx);
5529 DUK_INTERNAL_DECL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5530 DUK_INTERNAL_DECL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5531 
5532 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);
5533 
5534 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5535 
5536 DUK_INTERNAL_DECL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5537 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5538 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask);
5539 #define duk_require_hobject_promote_lfunc(thr,idx) \
5540 	duk_require_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5541 #define duk_get_hobject_promote_lfunc(thr,idx) \
5542 	duk_get_hobject_promote_mask((thr), (idx), DUK_TYPE_MASK_LIGHTFUNC)
5543 
5544 #if 0  /*unused*/
5545 DUK_INTERNAL_DECL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx);
5546 #endif
5547 
5548 DUK_INTERNAL_DECL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx);
5549 DUK_INTERNAL_DECL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx);
5550 DUK_INTERNAL_DECL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx);
5551 DUK_INTERNAL_DECL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5552 DUK_INTERNAL_DECL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5553 
5554 DUK_INTERNAL_DECL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv);
5555 
5556 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx);
5557 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_m1(duk_hthread *thr);
5558 DUK_INTERNAL_DECL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx);
5559 
5560 DUK_INTERNAL_DECL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx);
5561 
5562 DUK_INTERNAL_DECL duk_double_t duk_to_number_m1(duk_hthread *thr);
5563 DUK_INTERNAL_DECL duk_double_t duk_to_number_m2(duk_hthread *thr);
5564 
5565 DUK_INTERNAL_DECL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr);
5566 
5567 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
5568 DUK_INTERNAL_DECL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx);
5569 #endif
5570 DUK_INTERNAL_DECL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects);
5571 
5572 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 */
5573 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);
5574 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);
5575 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5576 DUK_INTERNAL_DECL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx);
5577 #endif
5578 DUK_INTERNAL_DECL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx);
5579 
5580 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx);
5581 DUK_INTERNAL_DECL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx);
5582 DUK_INTERNAL_DECL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len);
5583 DUK_INTERNAL_DECL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx);
5584 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx);
5585 DUK_INTERNAL_DECL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx);
5586 DUK_INTERNAL_DECL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx);
5587 DUK_INTERNAL_DECL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx);
5588 DUK_INTERNAL_DECL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx);
5589 
5590 DUK_INTERNAL_DECL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum);
5591 
5592 DUK_INTERNAL_DECL void duk_push_hstring(duk_hthread *thr, duk_hstring *h);
5593 DUK_INTERNAL_DECL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx);
5594 DUK_INTERNAL_DECL void duk_push_hstring_empty(duk_hthread *thr);
5595 DUK_INTERNAL_DECL void duk_push_hobject(duk_hthread *thr, duk_hobject *h);
5596 DUK_INTERNAL_DECL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h);
5597 #define duk_push_hthread(thr,h) \
5598 	duk_push_hobject((thr), (duk_hobject *) (h))
5599 #define duk_push_hnatfunc(thr,h) \
5600 	duk_push_hobject((thr), (duk_hobject *) (h))
5601 DUK_INTERNAL_DECL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx);
5602 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);
5603 DUK_INTERNAL_DECL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto);
5604 DUK_INTERNAL_DECL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr);
5605 DUK_INTERNAL_DECL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr);
5606 DUK_INTERNAL_DECL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5607 DUK_INTERNAL_DECL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs);
5608 
5609 /* XXX: duk_push_harray() and duk_push_hcompfunc() are inconsistent with
5610  * duk_push_hobject() etc which don't create a new value.
5611  */
5612 DUK_INTERNAL_DECL duk_harray *duk_push_harray(duk_hthread *thr);
5613 DUK_INTERNAL_DECL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size);
5614 DUK_INTERNAL_DECL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size);
5615 
5616 DUK_INTERNAL_DECL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz);
5617 DUK_INTERNAL_DECL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags);
5618 DUK_INTERNAL_DECL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv);
5619 DUK_INTERNAL_DECL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv);
5620 #if 0  /* not used yet */
5621 DUK_INTERNAL_DECL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h);
5622 #endif
5623 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
5624 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);
5625 #endif
5626 
5627 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len);
5628 DUK_INTERNAL_DECL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len);
5629 
5630 DUK_INTERNAL_DECL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx);
5631 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv);
5632 DUK_INTERNAL_DECL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv);
5633 
5634 /* The duk_xxx_prop_stridx_short() variants expect their arguments to be short
5635  * enough to be packed into a single 32-bit integer argument.  Argument limits
5636  * vary per call; typically 16 bits are assigned to the signed value stack index
5637  * and the stridx.  In practice these work well for footprint with constant
5638  * arguments and such call sites are also easiest to verify to be correct.
5639  */
5640 
5641 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [val] */
5642 DUK_INTERNAL_DECL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5643 #define duk_get_prop_stridx_short(thr,obj_idx,stridx) \
5644 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5645 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5646 	 duk_get_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5647 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);  /* [] -> [] */
5648 
5649 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [val] -> [] */
5650 DUK_INTERNAL_DECL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5651 #define duk_put_prop_stridx_short(thr,obj_idx,stridx) \
5652 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x8000L && (duk_int_t) (obj_idx) <= 0x7fffL), \
5653 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5654 	 duk_put_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5655 
5656 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5657 #if 0  /* Too few call sites to be useful. */
5658 DUK_INTERNAL_DECL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5659 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5660 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5661 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5662 	 duk_del_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5663 #endif
5664 #define duk_del_prop_stridx_short(thr,obj_idx,stridx) \
5665 	duk_del_prop_stridx((thr), (obj_idx), (stridx))
5666 
5667 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);     /* [] -> [] */
5668 #if 0  /* Too few call sites to be useful. */
5669 DUK_INTERNAL_DECL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5670 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5671 	(DUK_ASSERT_EXPR((obj_idx) >= -0x8000L && (obj_idx) <= 0x7fffL), \
5672 	 DUK_ASSERT_EXPR((stridx) >= 0 && (stridx) <= 0xffffL), \
5673 	 duk_has_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 16) + ((duk_uint_t) (stridx))))
5674 #endif
5675 #define duk_has_prop_stridx_short(thr,obj_idx,stridx) \
5676 	duk_has_prop_stridx((thr), (obj_idx), (stridx))
5677 
5678 DUK_INTERNAL_DECL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags);  /* [key val] -> [] */
5679 
5680 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] -> [] */
5681 
5682 /* XXX: Because stridx and desc_flags have a limited range, this call could
5683  * always pack stridx and desc_flags into a single argument.
5684  */
5685 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] -> [] */
5686 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args);
5687 #define duk_xdef_prop_stridx_short(thr,obj_idx,stridx,desc_flags) \
5688 	(DUK_ASSERT_EXPR((duk_int_t) (obj_idx) >= -0x80L && (duk_int_t) (obj_idx) <= 0x7fL), \
5689 	 DUK_ASSERT_EXPR((duk_int_t) (stridx) >= 0 && (duk_int_t) (stridx) <= 0xffffL), \
5690 	 DUK_ASSERT_EXPR((duk_int_t) (desc_flags) >= 0 && (duk_int_t) (desc_flags) <= 0xffL), \
5691 	 duk_xdef_prop_stridx_short_raw((thr), (((duk_uint_t) (obj_idx)) << 24) + (((duk_uint_t) (stridx)) << 8) + (duk_uint_t) (desc_flags)))
5692 
5693 #define duk_xdef_prop_wec(thr,obj_idx) \
5694 	duk_xdef_prop((thr), (obj_idx), DUK_PROPDESC_FLAGS_WEC)
5695 #define duk_xdef_prop_index_wec(thr,obj_idx,arr_idx) \
5696 	duk_xdef_prop_index((thr), (obj_idx), (arr_idx), DUK_PROPDESC_FLAGS_WEC)
5697 #define duk_xdef_prop_stridx_wec(thr,obj_idx,stridx) \
5698 	duk_xdef_prop_stridx((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5699 #define duk_xdef_prop_stridx_short_wec(thr,obj_idx,stridx) \
5700 	duk_xdef_prop_stridx_short((thr), (obj_idx), (stridx), DUK_PROPDESC_FLAGS_WEC)
5701 
5702 #if 0  /*unused*/
5703 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);  /* [] -> [] */
5704 #endif
5705 
5706 DUK_INTERNAL_DECL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx);  /* [] -> [] */
5707 
5708 DUK_INTERNAL_DECL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx);
5709 
5710 DUK_INTERNAL_DECL void duk_pack(duk_hthread *thr, duk_idx_t count);
5711 DUK_INTERNAL_DECL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx);
5712 #if 0
5713 DUK_INTERNAL_DECL void duk_unpack(duk_hthread *thr);
5714 #endif
5715 
5716 DUK_INTERNAL_DECL void duk_require_constructor_call(duk_hthread *thr);
5717 DUK_INTERNAL_DECL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx);
5718 DUK_INTERNAL_DECL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h);
5719 
5720 DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_hthread *thr);
5721 
5722 DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top);
5723 DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr);
5724 
5725 DUK_INTERNAL_DECL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count);
5726 DUK_INTERNAL_DECL void duk_pop_unsafe(duk_hthread *thr);
5727 DUK_INTERNAL_DECL void duk_pop_2_unsafe(duk_hthread *thr);
5728 DUK_INTERNAL_DECL void duk_pop_3_unsafe(duk_hthread *thr);
5729 DUK_INTERNAL_DECL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count);
5730 DUK_INTERNAL_DECL void duk_pop_nodecref_unsafe(duk_hthread *thr);
5731 DUK_INTERNAL_DECL void duk_pop_2_nodecref_unsafe(duk_hthread *thr);
5732 DUK_INTERNAL_DECL void duk_pop_3_nodecref_unsafe(duk_hthread *thr);
5733 DUK_INTERNAL_DECL void duk_pop_undefined(duk_hthread *thr);
5734 
5735 DUK_INTERNAL_DECL void duk_compact_m1(duk_hthread *thr);
5736 
5737 DUK_INTERNAL_DECL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze);
5738 
5739 DUK_INTERNAL_DECL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx);
5740 DUK_INTERNAL_DECL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count);
5741 
5742 DUK_INTERNAL_DECL void duk_concat_2(duk_hthread *thr);
5743 
5744 DUK_INTERNAL_DECL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
5745 
5746 #if defined(DUK_USE_SYMBOL_BUILTIN)
5747 DUK_INTERNAL_DECL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint);
5748 #endif
5749 
5750 /* Raw internal valstack access macros: access is unsafe so call site
5751  * must have a guarantee that the index is valid.  When that is the case,
5752  * using these macro results in faster and smaller code than duk_get_tval().
5753  * Both 'ctx' and 'idx' are evaluted multiple times, but only for asserts.
5754  */
5755 #define DUK_ASSERT_VALID_NEGIDX(thr,idx) \
5756 	(DUK_ASSERT_EXPR((duk_int_t) (idx) < 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5757 #define DUK_ASSERT_VALID_POSIDX(thr,idx) \
5758 	(DUK_ASSERT_EXPR((duk_int_t) (idx) >= 0), DUK_ASSERT_EXPR(duk_is_valid_index((thr), (idx))))
5759 #define DUK_GET_TVAL_NEGIDX(thr,idx) \
5760 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_top + (idx))
5761 #define DUK_GET_TVAL_POSIDX(thr,idx) \
5762 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), ((duk_hthread *) (thr))->valstack_bottom + (idx))
5763 #define DUK_GET_HOBJECT_NEGIDX(thr,idx) \
5764 	(DUK_ASSERT_VALID_NEGIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_top + (idx)))
5765 #define DUK_GET_HOBJECT_POSIDX(thr,idx) \
5766 	(DUK_ASSERT_VALID_POSIDX((thr),(idx)), DUK_TVAL_GET_OBJECT(((duk_hthread *) (thr))->valstack_bottom + (idx)))
5767 
5768 #define DUK_GET_THIS_TVAL_PTR(thr) \
5769 	(DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
5770 	 (thr)->valstack_bottom - 1)
5771 
5772 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr);
5773 DUK_INTERNAL_DECL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr);
5774 DUK_INTERNAL_DECL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr);
5775 
5776 #endif  /* DUK_API_INTERNAL_H_INCLUDED */
5777 /* #include duk_hstring.h */
5778 #line 1 "duk_hstring.h"
5779 /*
5780  *  Heap string representation.
5781  *
5782  *  Strings are byte sequences ordinarily stored in extended UTF-8 format,
5783  *  allowing values larger than the official UTF-8 range (used internally)
5784  *  and also allowing UTF-8 encoding of surrogate pairs (CESU-8 format).
5785  *  Strings may also be invalid UTF-8 altogether which is the case e.g. with
5786  *  strings used as internal property names and raw buffers converted to
5787  *  strings.  In such cases the 'clen' field contains an inaccurate value.
5788  *
5789  *  ECMAScript requires support for 32-bit long strings.  However, since each
5790  *  16-bit codepoint can take 3 bytes in CESU-8, this representation can only
5791  *  support about 1.4G codepoint long strings in extreme cases.  This is not
5792  *  really a practical issue.
5793  */
5794 
5795 #if !defined(DUK_HSTRING_H_INCLUDED)
5796 #define DUK_HSTRING_H_INCLUDED
5797 
5798 /* Impose a maximum string length for now.  Restricted artificially to
5799  * ensure adding a heap header length won't overflow size_t.  The limit
5800  * should be synchronized with DUK_HBUFFER_MAX_BYTELEN.
5801  *
5802  * E5.1 makes provisions to support strings longer than 4G characters.
5803  * This limit should be eliminated on 64-bit platforms (and increased
5804  * closer to maximum support on 32-bit platforms).
5805  */
5806 
5807 #if defined(DUK_USE_STRLEN16)
5808 #define DUK_HSTRING_MAX_BYTELEN                     (0x0000ffffUL)
5809 #else
5810 #define DUK_HSTRING_MAX_BYTELEN                     (0x7fffffffUL)
5811 #endif
5812 
5813 /* XXX: could add flags for "is valid CESU-8" (ECMAScript compatible strings),
5814  * "is valid UTF-8", "is valid extended UTF-8" (internal strings are not,
5815  * regexp bytecode is), and "contains non-BMP characters".  These are not
5816  * needed right now.
5817  */
5818 
5819 /* With lowmem builds the high 16 bits of duk_heaphdr are used for other
5820  * purposes, so this leaves 7 duk_heaphdr flags and 9 duk_hstring flags.
5821  */
5822 #define DUK_HSTRING_FLAG_ASCII                      DUK_HEAPHDR_USER_FLAG(0)  /* string is ASCII, clen == blen */
5823 #define DUK_HSTRING_FLAG_ARRIDX                     DUK_HEAPHDR_USER_FLAG(1)  /* string is a valid array index */
5824 #define DUK_HSTRING_FLAG_SYMBOL                     DUK_HEAPHDR_USER_FLAG(2)  /* string is a symbol (invalid utf-8) */
5825 #define DUK_HSTRING_FLAG_HIDDEN                     DUK_HEAPHDR_USER_FLAG(3)  /* string is a hidden symbol (implies symbol, Duktape 1.x internal string) */
5826 #define DUK_HSTRING_FLAG_RESERVED_WORD              DUK_HEAPHDR_USER_FLAG(4)  /* string is a reserved word (non-strict) */
5827 #define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD       DUK_HEAPHDR_USER_FLAG(5)  /* string is a reserved word (strict) */
5828 #define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS          DUK_HEAPHDR_USER_FLAG(6)  /* string is 'eval' or 'arguments' */
5829 #define DUK_HSTRING_FLAG_EXTDATA                    DUK_HEAPHDR_USER_FLAG(7)  /* string data is external (duk_hstring_external) */
5830 #define DUK_HSTRING_FLAG_PINNED_LITERAL             DUK_HEAPHDR_USER_FLAG(8)  /* string is a literal, and pinned */
5831 
5832 #define DUK_HSTRING_HAS_ASCII(x)                    DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5833 #define DUK_HSTRING_HAS_ARRIDX(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5834 #define DUK_HSTRING_HAS_SYMBOL(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5835 #define DUK_HSTRING_HAS_HIDDEN(x)                   DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5836 #define DUK_HSTRING_HAS_RESERVED_WORD(x)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5837 #define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5838 #define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5839 #define DUK_HSTRING_HAS_EXTDATA(x)                  DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5840 #define DUK_HSTRING_HAS_PINNED_LITERAL(x)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5841 
5842 #define DUK_HSTRING_SET_ASCII(x)                    DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5843 #define DUK_HSTRING_SET_ARRIDX(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5844 #define DUK_HSTRING_SET_SYMBOL(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5845 #define DUK_HSTRING_SET_HIDDEN(x)                   DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5846 #define DUK_HSTRING_SET_RESERVED_WORD(x)            DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5847 #define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x)     DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5848 #define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x)        DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5849 #define DUK_HSTRING_SET_EXTDATA(x)                  DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5850 #define DUK_HSTRING_SET_PINNED_LITERAL(x)           DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5851 
5852 #define DUK_HSTRING_CLEAR_ASCII(x)                  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ASCII)
5853 #define DUK_HSTRING_CLEAR_ARRIDX(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
5854 #define DUK_HSTRING_CLEAR_SYMBOL(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_SYMBOL)
5855 #define DUK_HSTRING_CLEAR_HIDDEN(x)                 DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_HIDDEN)
5856 #define DUK_HSTRING_CLEAR_RESERVED_WORD(x)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
5857 #define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
5858 #define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
5859 #define DUK_HSTRING_CLEAR_EXTDATA(x)                DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
5860 #define DUK_HSTRING_CLEAR_PINNED_LITERAL(x)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_PINNED_LITERAL)
5861 
5862 #if 0  /* Slightly smaller code without explicit flag, but explicit flag
5863         * is very useful when 'clen' is dropped.
5864         */
5865 #define DUK_HSTRING_IS_ASCII(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
5866 #endif
5867 #define DUK_HSTRING_IS_ASCII(x)                     DUK_HSTRING_HAS_ASCII((x))  /* lazily set! */
5868 #define DUK_HSTRING_IS_EMPTY(x)                     (DUK_HSTRING_GET_BYTELEN((x)) == 0)
5869 
5870 #if defined(DUK_USE_STRHASH16)
5871 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hdr.h_flags >> 16)
5872 #define DUK_HSTRING_SET_HASH(x,v) do { \
5873 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | ((v) << 16); \
5874 	} while (0)
5875 #else
5876 #define DUK_HSTRING_GET_HASH(x)                     ((x)->hash)
5877 #define DUK_HSTRING_SET_HASH(x,v) do { \
5878 		(x)->hash = (v); \
5879 	} while (0)
5880 #endif
5881 
5882 #if defined(DUK_USE_STRLEN16)
5883 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->hdr.h_strextra16)
5884 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5885 		(x)->hdr.h_strextra16 = (v); \
5886 	} while (0)
5887 #if defined(DUK_USE_HSTRING_CLEN)
5888 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5889 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5890 		(x)->clen16 = (v); \
5891 	} while (0)
5892 #else
5893 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5894 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5895 		DUK_ASSERT(0);  /* should never be called */ \
5896 	} while (0)
5897 #endif
5898 #else
5899 #define DUK_HSTRING_GET_BYTELEN(x)                  ((x)->blen)
5900 #define DUK_HSTRING_SET_BYTELEN(x,v) do { \
5901 		(x)->blen = (v); \
5902 	} while (0)
5903 #define DUK_HSTRING_GET_CHARLEN(x)                  duk_hstring_get_charlen((x))
5904 #define DUK_HSTRING_SET_CHARLEN(x,v) do { \
5905 		(x)->clen = (v); \
5906 	} while (0)
5907 #endif
5908 
5909 #if defined(DUK_USE_HSTRING_EXTDATA)
5910 #define DUK_HSTRING_GET_EXTDATA(x) \
5911 	((x)->extdata)
5912 #define DUK_HSTRING_GET_DATA(x) \
5913 	(DUK_HSTRING_HAS_EXTDATA((x)) ? \
5914 		DUK_HSTRING_GET_EXTDATA((const duk_hstring_external *) (x)) : ((const duk_uint8_t *) ((x) + 1)))
5915 #else
5916 #define DUK_HSTRING_GET_DATA(x) \
5917 	((const duk_uint8_t *) ((x) + 1))
5918 #endif
5919 
5920 #define DUK_HSTRING_GET_DATA_END(x) \
5921 	(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
5922 
5923 /* Marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest
5924  * valid).
5925  */
5926 #define DUK_HSTRING_NO_ARRAY_INDEX  (0xffffffffUL)
5927 
5928 #if defined(DUK_USE_HSTRING_ARRIDX)
5929 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  ((h)->arridx)
5930 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  ((h)->arridx)
5931 #else
5932 /* Get array index related to string (or return DUK_HSTRING_NO_ARRAY_INDEX);
5933  * avoids helper call if string has no array index value.
5934  */
5935 #define DUK_HSTRING_GET_ARRIDX_FAST(h)  \
5936 	(DUK_HSTRING_HAS_ARRIDX((h)) ? duk_js_to_arrayindex_hstring_fast_known((h)) : DUK_HSTRING_NO_ARRAY_INDEX)
5937 
5938 /* Slower but more compact variant. */
5939 #define DUK_HSTRING_GET_ARRIDX_SLOW(h)  \
5940 	(duk_js_to_arrayindex_hstring_fast((h)))
5941 #endif
5942 
5943 /* XXX: these actually fit into duk_hstring */
5944 #define DUK_SYMBOL_TYPE_HIDDEN 0
5945 #define DUK_SYMBOL_TYPE_GLOBAL 1
5946 #define DUK_SYMBOL_TYPE_LOCAL 2
5947 #define DUK_SYMBOL_TYPE_WELLKNOWN 3
5948 
5949 /*
5950  *  Misc
5951  */
5952 
5953 struct duk_hstring {
5954 	/* Smaller heaphdr than for other objects, because strings are held
5955 	 * in string intern table which requires no link pointers.  Much of
5956 	 * the 32-bit flags field is unused by flags, so we can stuff a 16-bit
5957 	 * field in there.
5958 	 */
5959 	duk_heaphdr_string hdr;
5960 
5961 	/* String hash. */
5962 #if defined(DUK_USE_STRHASH16)
5963 	/* If 16-bit hash is in use, stuff it into duk_heaphdr_string flags. */
5964 #else
5965 	duk_uint32_t hash;
5966 #endif
5967 
5968 	/* Precomputed array index (or DUK_HSTRING_NO_ARRAY_INDEX). */
5969 #if defined(DUK_USE_HSTRING_ARRIDX)
5970 	duk_uarridx_t arridx;
5971 #endif
5972 
5973 	/* Length in bytes (not counting NUL term). */
5974 #if defined(DUK_USE_STRLEN16)
5975 	/* placed in duk_heaphdr_string */
5976 #else
5977 	duk_uint32_t blen;
5978 #endif
5979 
5980 	/* Length in codepoints (must be E5 compatible). */
5981 #if defined(DUK_USE_STRLEN16)
5982 #if defined(DUK_USE_HSTRING_CLEN)
5983 	duk_uint16_t clen16;
5984 #else
5985 	/* computed live */
5986 #endif
5987 #else
5988 	duk_uint32_t clen;
5989 #endif
5990 
5991 	/*
5992 	 *  String data of 'blen+1' bytes follows (+1 for NUL termination
5993 	 *  convenience for C API).  No alignment needs to be guaranteed
5994 	 *  for strings, but fields above should guarantee alignment-by-4
5995 	 *  (but not alignment-by-8).
5996 	 */
5997 };
5998 
5999 /* The external string struct is defined even when the feature is inactive. */
6000 struct duk_hstring_external {
6001 	duk_hstring str;
6002 
6003 	/*
6004 	 *  For an external string, the NUL-terminated string data is stored
6005 	 *  externally.  The user must guarantee that data behind this pointer
6006 	 *  doesn't change while it's used.
6007 	 */
6008 
6009 	const duk_uint8_t *extdata;
6010 };
6011 
6012 /*
6013  *  Prototypes
6014  */
6015 
6016 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);
6017 DUK_INTERNAL_DECL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr);
6018 DUK_INTERNAL_DECL duk_size_t duk_hstring_get_charlen(duk_hstring *h);
6019 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
6020 DUK_INTERNAL_DECL void duk_hstring_init_charlen(duk_hstring *h);
6021 #endif
6022 
6023 #endif  /* DUK_HSTRING_H_INCLUDED */
6024 /* #include duk_hobject.h */
6025 #line 1 "duk_hobject.h"
6026 /*
6027  *  Heap object representation.
6028  *
6029  *  Heap objects are used for ECMAScript objects, arrays, and functions,
6030  *  but also for internal control like declarative and object environment
6031  *  records.  Compiled functions, native functions, and threads are also
6032  *  objects but with an extended C struct.
6033  *
6034  *  Objects provide the required ECMAScript semantics and exotic behaviors
6035  *  especially for property access.
6036  *
6037  *  Properties are stored in three conceptual parts:
6038  *
6039  *    1. A linear 'entry part' contains ordered key-value-attributes triples
6040  *       and is the main method of string properties.
6041  *
6042  *    2. An optional linear 'array part' is used for array objects to store a
6043  *       (dense) range of [0,N[ array indexed entries with default attributes
6044  *       (writable, enumerable, configurable).  If the array part would become
6045  *       sparse or non-default attributes are required, the array part is
6046  *       abandoned and moved to the 'entry part'.
6047  *
6048  *    3. An optional 'hash part' is used to optimize lookups of the entry
6049  *       part; it is used only for objects with sufficiently many properties
6050  *       and can be abandoned without loss of information.
6051  *
6052  *  These three conceptual parts are stored in a single memory allocated area.
6053  *  This minimizes memory allocation overhead but also means that all three
6054  *  parts are resized together, and makes property access a bit complicated.
6055  */
6056 
6057 #if !defined(DUK_HOBJECT_H_INCLUDED)
6058 #define DUK_HOBJECT_H_INCLUDED
6059 
6060 /* Object flags.  Make sure this stays in sync with debugger object
6061  * inspection code.
6062  */
6063 
6064 /* XXX: some flags are object subtype specific (e.g. common to all function
6065  * subtypes, duk_harray, etc) and could be reused for different subtypes.
6066  */
6067 #define DUK_HOBJECT_FLAG_EXTENSIBLE            DUK_HEAPHDR_USER_FLAG(0)   /* object is extensible */
6068 #define DUK_HOBJECT_FLAG_CONSTRUCTABLE         DUK_HEAPHDR_USER_FLAG(1)   /* object is constructable */
6069 #define DUK_HOBJECT_FLAG_CALLABLE              DUK_HEAPHDR_USER_FLAG(2)   /* object is callable */
6070 #define DUK_HOBJECT_FLAG_BOUNDFUNC             DUK_HEAPHDR_USER_FLAG(3)   /* object established using Function.prototype.bind() */
6071 #define DUK_HOBJECT_FLAG_COMPFUNC              DUK_HEAPHDR_USER_FLAG(4)   /* object is a compiled function (duk_hcompfunc) */
6072 #define DUK_HOBJECT_FLAG_NATFUNC               DUK_HEAPHDR_USER_FLAG(5)   /* object is a native function (duk_hnatfunc) */
6073 #define DUK_HOBJECT_FLAG_BUFOBJ                DUK_HEAPHDR_USER_FLAG(6)   /* object is a buffer object (duk_hbufobj) (always exotic) */
6074 #define DUK_HOBJECT_FLAG_FASTREFS              DUK_HEAPHDR_USER_FLAG(7)   /* object has no fields needing DECREF/marking beyond base duk_hobject header */
6075 #define DUK_HOBJECT_FLAG_ARRAY_PART            DUK_HEAPHDR_USER_FLAG(8)   /* object has an array part (a_size may still be 0) */
6076 #define DUK_HOBJECT_FLAG_STRICT                DUK_HEAPHDR_USER_FLAG(9)   /* function: function object is strict */
6077 #define DUK_HOBJECT_FLAG_NOTAIL                DUK_HEAPHDR_USER_FLAG(10)  /* function: function must not be tail called */
6078 #define DUK_HOBJECT_FLAG_NEWENV                DUK_HEAPHDR_USER_FLAG(11)  /* function: create new environment when called (see duk_hcompfunc) */
6079 #define DUK_HOBJECT_FLAG_NAMEBINDING           DUK_HEAPHDR_USER_FLAG(12)  /* function: create binding for func name (function templates only, used for named function expressions) */
6080 #define DUK_HOBJECT_FLAG_CREATEARGS            DUK_HEAPHDR_USER_FLAG(13)  /* function: create an arguments object on function call */
6081 #define DUK_HOBJECT_FLAG_HAVE_FINALIZER        DUK_HEAPHDR_USER_FLAG(14)  /* object has a callable (own) finalizer property */
6082 #define DUK_HOBJECT_FLAG_EXOTIC_ARRAY          DUK_HEAPHDR_USER_FLAG(15)  /* 'Array' object, array length and index exotic behavior */
6083 #define DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ      DUK_HEAPHDR_USER_FLAG(16)  /* 'String' object, array index exotic behavior */
6084 #define DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS      DUK_HEAPHDR_USER_FLAG(17)  /* 'Arguments' object and has arguments exotic behavior (non-strict callee) */
6085 #define DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ       DUK_HEAPHDR_USER_FLAG(18)  /* 'Proxy' object */
6086 #define DUK_HOBJECT_FLAG_SPECIAL_CALL          DUK_HEAPHDR_USER_FLAG(19)  /* special casing in call behavior, for .call(), .apply(), etc. */
6087 
6088 #define DUK_HOBJECT_FLAG_CLASS_BASE            DUK_HEAPHDR_USER_FLAG_NUMBER(20)
6089 #define DUK_HOBJECT_FLAG_CLASS_BITS            5
6090 
6091 #define DUK_HOBJECT_GET_CLASS_NUMBER(h)        \
6092 	DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS)
6093 #define DUK_HOBJECT_SET_CLASS_NUMBER(h,v)      \
6094 	DUK_HEAPHDR_SET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS, (v))
6095 
6096 #define DUK_HOBJECT_GET_CLASS_MASK(h)          \
6097 	(1UL << DUK_HEAPHDR_GET_FLAG_RANGE(&(h)->hdr, DUK_HOBJECT_FLAG_CLASS_BASE, DUK_HOBJECT_FLAG_CLASS_BITS))
6098 
6099 /* Macro for creating flag initializer from a class number.
6100  * Unsigned type cast is needed to avoid warnings about coercing
6101  * a signed integer to an unsigned one; the largest class values
6102  * have the highest bit (bit 31) set which causes this.
6103  */
6104 #define DUK_HOBJECT_CLASS_AS_FLAGS(v)          (((duk_uint_t) (v)) << DUK_HOBJECT_FLAG_CLASS_BASE)
6105 
6106 /* E5 Section 8.6.2 + custom classes */
6107 #define DUK_HOBJECT_CLASS_NONE                 0
6108 #define DUK_HOBJECT_CLASS_OBJECT               1
6109 #define DUK_HOBJECT_CLASS_ARRAY                2
6110 #define DUK_HOBJECT_CLASS_FUNCTION             3
6111 #define DUK_HOBJECT_CLASS_ARGUMENTS            4
6112 #define DUK_HOBJECT_CLASS_BOOLEAN              5
6113 #define DUK_HOBJECT_CLASS_DATE                 6
6114 #define DUK_HOBJECT_CLASS_ERROR                7
6115 #define DUK_HOBJECT_CLASS_JSON                 8
6116 #define DUK_HOBJECT_CLASS_MATH                 9
6117 #define DUK_HOBJECT_CLASS_NUMBER               10
6118 #define DUK_HOBJECT_CLASS_REGEXP               11
6119 #define DUK_HOBJECT_CLASS_STRING               12
6120 #define DUK_HOBJECT_CLASS_GLOBAL               13
6121 #define DUK_HOBJECT_CLASS_SYMBOL               14
6122 #define DUK_HOBJECT_CLASS_OBJENV               15  /* custom */
6123 #define DUK_HOBJECT_CLASS_DECENV               16  /* custom */
6124 #define DUK_HOBJECT_CLASS_POINTER              17  /* custom */
6125 #define DUK_HOBJECT_CLASS_THREAD               18  /* custom; implies DUK_HOBJECT_IS_THREAD */
6126 #define DUK_HOBJECT_CLASS_BUFOBJ_MIN           19
6127 #define DUK_HOBJECT_CLASS_ARRAYBUFFER          19  /* implies DUK_HOBJECT_IS_BUFOBJ */
6128 #define DUK_HOBJECT_CLASS_DATAVIEW             20
6129 #define DUK_HOBJECT_CLASS_INT8ARRAY            21
6130 #define DUK_HOBJECT_CLASS_UINT8ARRAY           22
6131 #define DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY    23
6132 #define DUK_HOBJECT_CLASS_INT16ARRAY           24
6133 #define DUK_HOBJECT_CLASS_UINT16ARRAY          25
6134 #define DUK_HOBJECT_CLASS_INT32ARRAY           26
6135 #define DUK_HOBJECT_CLASS_UINT32ARRAY          27
6136 #define DUK_HOBJECT_CLASS_FLOAT32ARRAY         28
6137 #define DUK_HOBJECT_CLASS_FLOAT64ARRAY         29
6138 #define DUK_HOBJECT_CLASS_BUFOBJ_MAX           29
6139 #define DUK_HOBJECT_CLASS_MAX                  29
6140 
6141 /* Class masks. */
6142 #define DUK_HOBJECT_CMASK_ALL                  ((1UL << (DUK_HOBJECT_CLASS_MAX + 1)) - 1UL)
6143 #define DUK_HOBJECT_CMASK_NONE                 (1UL << DUK_HOBJECT_CLASS_NONE)
6144 #define DUK_HOBJECT_CMASK_ARGUMENTS            (1UL << DUK_HOBJECT_CLASS_ARGUMENTS)
6145 #define DUK_HOBJECT_CMASK_ARRAY                (1UL << DUK_HOBJECT_CLASS_ARRAY)
6146 #define DUK_HOBJECT_CMASK_BOOLEAN              (1UL << DUK_HOBJECT_CLASS_BOOLEAN)
6147 #define DUK_HOBJECT_CMASK_DATE                 (1UL << DUK_HOBJECT_CLASS_DATE)
6148 #define DUK_HOBJECT_CMASK_ERROR                (1UL << DUK_HOBJECT_CLASS_ERROR)
6149 #define DUK_HOBJECT_CMASK_FUNCTION             (1UL << DUK_HOBJECT_CLASS_FUNCTION)
6150 #define DUK_HOBJECT_CMASK_JSON                 (1UL << DUK_HOBJECT_CLASS_JSON)
6151 #define DUK_HOBJECT_CMASK_MATH                 (1UL << DUK_HOBJECT_CLASS_MATH)
6152 #define DUK_HOBJECT_CMASK_NUMBER               (1UL << DUK_HOBJECT_CLASS_NUMBER)
6153 #define DUK_HOBJECT_CMASK_OBJECT               (1UL << DUK_HOBJECT_CLASS_OBJECT)
6154 #define DUK_HOBJECT_CMASK_REGEXP               (1UL << DUK_HOBJECT_CLASS_REGEXP)
6155 #define DUK_HOBJECT_CMASK_STRING               (1UL << DUK_HOBJECT_CLASS_STRING)
6156 #define DUK_HOBJECT_CMASK_GLOBAL               (1UL << DUK_HOBJECT_CLASS_GLOBAL)
6157 #define DUK_HOBJECT_CMASK_SYMBOL               (1UL << DUK_HOBJECT_CLASS_SYMBOL)
6158 #define DUK_HOBJECT_CMASK_OBJENV               (1UL << DUK_HOBJECT_CLASS_OBJENV)
6159 #define DUK_HOBJECT_CMASK_DECENV               (1UL << DUK_HOBJECT_CLASS_DECENV)
6160 #define DUK_HOBJECT_CMASK_POINTER              (1UL << DUK_HOBJECT_CLASS_POINTER)
6161 #define DUK_HOBJECT_CMASK_ARRAYBUFFER          (1UL << DUK_HOBJECT_CLASS_ARRAYBUFFER)
6162 #define DUK_HOBJECT_CMASK_DATAVIEW             (1UL << DUK_HOBJECT_CLASS_DATAVIEW)
6163 #define DUK_HOBJECT_CMASK_INT8ARRAY            (1UL << DUK_HOBJECT_CLASS_INT8ARRAY)
6164 #define DUK_HOBJECT_CMASK_UINT8ARRAY           (1UL << DUK_HOBJECT_CLASS_UINT8ARRAY)
6165 #define DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY    (1UL << DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY)
6166 #define DUK_HOBJECT_CMASK_INT16ARRAY           (1UL << DUK_HOBJECT_CLASS_INT16ARRAY)
6167 #define DUK_HOBJECT_CMASK_UINT16ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT16ARRAY)
6168 #define DUK_HOBJECT_CMASK_INT32ARRAY           (1UL << DUK_HOBJECT_CLASS_INT32ARRAY)
6169 #define DUK_HOBJECT_CMASK_UINT32ARRAY          (1UL << DUK_HOBJECT_CLASS_UINT32ARRAY)
6170 #define DUK_HOBJECT_CMASK_FLOAT32ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT32ARRAY)
6171 #define DUK_HOBJECT_CMASK_FLOAT64ARRAY         (1UL << DUK_HOBJECT_CLASS_FLOAT64ARRAY)
6172 
6173 #define DUK_HOBJECT_CMASK_ALL_BUFOBJS \
6174 	(DUK_HOBJECT_CMASK_ARRAYBUFFER | \
6175 	 DUK_HOBJECT_CMASK_DATAVIEW | \
6176 	 DUK_HOBJECT_CMASK_INT8ARRAY | \
6177 	 DUK_HOBJECT_CMASK_UINT8ARRAY | \
6178 	 DUK_HOBJECT_CMASK_UINT8CLAMPEDARRAY | \
6179 	 DUK_HOBJECT_CMASK_INT16ARRAY | \
6180 	 DUK_HOBJECT_CMASK_UINT16ARRAY | \
6181 	 DUK_HOBJECT_CMASK_INT32ARRAY | \
6182 	 DUK_HOBJECT_CMASK_UINT32ARRAY | \
6183 	 DUK_HOBJECT_CMASK_FLOAT32ARRAY | \
6184 	 DUK_HOBJECT_CMASK_FLOAT64ARRAY)
6185 
6186 #define DUK_HOBJECT_IS_OBJENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_OBJENV)
6187 #define DUK_HOBJECT_IS_DECENV(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DECENV)
6188 #define DUK_HOBJECT_IS_ENV(h)                  (DUK_HOBJECT_IS_OBJENV((h)) || DUK_HOBJECT_IS_DECENV((h)))
6189 #define DUK_HOBJECT_IS_ARRAY(h)                DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))  /* Rely on class Array <=> exotic Array */
6190 #define DUK_HOBJECT_IS_BOUNDFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6191 #define DUK_HOBJECT_IS_COMPFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6192 #define DUK_HOBJECT_IS_NATFUNC(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6193 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6194 #define DUK_HOBJECT_IS_BUFOBJ(h)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6195 #else
6196 #define DUK_HOBJECT_IS_BUFOBJ(h)               0
6197 #endif
6198 #define DUK_HOBJECT_IS_THREAD(h)               (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_THREAD)
6199 #if defined(DUK_USE_ES6_PROXY)
6200 #define DUK_HOBJECT_IS_PROXY(h)                DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((h))
6201 #else
6202 #define DUK_HOBJECT_IS_PROXY(h)                0
6203 #endif
6204 
6205 #define DUK_HOBJECT_IS_NONBOUND_FUNCTION(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6206                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6207                                                         DUK_HOBJECT_FLAG_NATFUNC)
6208 
6209 #define DUK_HOBJECT_IS_FUNCTION(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, \
6210                                                         DUK_HOBJECT_FLAG_BOUNDFUNC | \
6211                                                         DUK_HOBJECT_FLAG_COMPFUNC | \
6212                                                         DUK_HOBJECT_FLAG_NATFUNC)
6213 
6214 #define DUK_HOBJECT_IS_CALLABLE(h)             DUK_HOBJECT_HAS_CALLABLE((h))
6215 
6216 /* Object has any exotic behavior(s). */
6217 #define DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS      (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6218                                                 DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS | \
6219                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6220                                                 DUK_HOBJECT_FLAG_BUFOBJ | \
6221                                                 DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6222 #define DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_EXOTIC_BEHAVIOR_FLAGS)
6223 
6224 /* Object has any virtual properties (not counting Proxy behavior). */
6225 #define DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS     (DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
6226                                                 DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ | \
6227                                                 DUK_HOBJECT_FLAG_BUFOBJ)
6228 #define DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(h)  DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_VIRTUAL_PROPERTY_FLAGS)
6229 
6230 #define DUK_HOBJECT_HAS_EXTENSIBLE(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6231 #define DUK_HOBJECT_HAS_CONSTRUCTABLE(h)       DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6232 #define DUK_HOBJECT_HAS_CALLABLE(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6233 #define DUK_HOBJECT_HAS_BOUNDFUNC(h)           DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6234 #define DUK_HOBJECT_HAS_COMPFUNC(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6235 #define DUK_HOBJECT_HAS_NATFUNC(h)             DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6236 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6237 #define DUK_HOBJECT_HAS_BUFOBJ(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6238 #else
6239 #define DUK_HOBJECT_HAS_BUFOBJ(h)              0
6240 #endif
6241 #define DUK_HOBJECT_HAS_FASTREFS(h)            DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6242 #define DUK_HOBJECT_HAS_ARRAY_PART(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6243 #define DUK_HOBJECT_HAS_STRICT(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6244 #define DUK_HOBJECT_HAS_NOTAIL(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6245 #define DUK_HOBJECT_HAS_NEWENV(h)              DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6246 #define DUK_HOBJECT_HAS_NAMEBINDING(h)         DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6247 #define DUK_HOBJECT_HAS_CREATEARGS(h)          DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6248 #define DUK_HOBJECT_HAS_HAVE_FINALIZER(h)      DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6249 #define DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6250 #define DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6251 #define DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6252 #if defined(DUK_USE_ES6_PROXY)
6253 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6254 #else
6255 #define DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)     0
6256 #endif
6257 #define DUK_HOBJECT_HAS_SPECIAL_CALL(h)        DUK_HEAPHDR_CHECK_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6258 
6259 #define DUK_HOBJECT_SET_EXTENSIBLE(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6260 #define DUK_HOBJECT_SET_CONSTRUCTABLE(h)       DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6261 #define DUK_HOBJECT_SET_CALLABLE(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6262 #define DUK_HOBJECT_SET_BOUNDFUNC(h)           DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6263 #define DUK_HOBJECT_SET_COMPFUNC(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6264 #define DUK_HOBJECT_SET_NATFUNC(h)             DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6265 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6266 #define DUK_HOBJECT_SET_BUFOBJ(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6267 #endif
6268 #define DUK_HOBJECT_SET_FASTREFS(h)            DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6269 #define DUK_HOBJECT_SET_ARRAY_PART(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6270 #define DUK_HOBJECT_SET_STRICT(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6271 #define DUK_HOBJECT_SET_NOTAIL(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6272 #define DUK_HOBJECT_SET_NEWENV(h)              DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6273 #define DUK_HOBJECT_SET_NAMEBINDING(h)         DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6274 #define DUK_HOBJECT_SET_CREATEARGS(h)          DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6275 #define DUK_HOBJECT_SET_HAVE_FINALIZER(h)      DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6276 #define DUK_HOBJECT_SET_EXOTIC_ARRAY(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6277 #define DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6278 #define DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(h)    DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6279 #if defined(DUK_USE_ES6_PROXY)
6280 #define DUK_HOBJECT_SET_EXOTIC_PROXYOBJ(h)     DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6281 #endif
6282 #define DUK_HOBJECT_SET_SPECIAL_CALL(h)        DUK_HEAPHDR_SET_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6283 
6284 #define DUK_HOBJECT_CLEAR_EXTENSIBLE(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXTENSIBLE)
6285 #define DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h)     DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CONSTRUCTABLE)
6286 #define DUK_HOBJECT_CLEAR_CALLABLE(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CALLABLE)
6287 #define DUK_HOBJECT_CLEAR_BOUNDFUNC(h)         DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BOUNDFUNC)
6288 #define DUK_HOBJECT_CLEAR_COMPFUNC(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_COMPFUNC)
6289 #define DUK_HOBJECT_CLEAR_NATFUNC(h)           DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NATFUNC)
6290 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6291 #define DUK_HOBJECT_CLEAR_BUFOBJ(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_BUFOBJ)
6292 #endif
6293 #define DUK_HOBJECT_CLEAR_FASTREFS(h)          DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_FASTREFS)
6294 #define DUK_HOBJECT_CLEAR_ARRAY_PART(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_ARRAY_PART)
6295 #define DUK_HOBJECT_CLEAR_STRICT(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_STRICT)
6296 #define DUK_HOBJECT_CLEAR_NOTAIL(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NOTAIL)
6297 #define DUK_HOBJECT_CLEAR_NEWENV(h)            DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NEWENV)
6298 #define DUK_HOBJECT_CLEAR_NAMEBINDING(h)       DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_NAMEBINDING)
6299 #define DUK_HOBJECT_CLEAR_CREATEARGS(h)        DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_CREATEARGS)
6300 #define DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h)    DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_HAVE_FINALIZER)
6301 #define DUK_HOBJECT_CLEAR_EXOTIC_ARRAY(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARRAY)
6302 #define DUK_HOBJECT_CLEAR_EXOTIC_STRINGOBJ(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ)
6303 #define DUK_HOBJECT_CLEAR_EXOTIC_ARGUMENTS(h)  DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS)
6304 #if defined(DUK_USE_ES6_PROXY)
6305 #define DUK_HOBJECT_CLEAR_EXOTIC_PROXYOBJ(h)   DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ)
6306 #endif
6307 #define DUK_HOBJECT_CLEAR_SPECIAL_CALL(h)      DUK_HEAPHDR_CLEAR_FLAG_BITS(&(h)->hdr, DUK_HOBJECT_FLAG_SPECIAL_CALL)
6308 
6309 /* Object can/cannot use FASTREFS, i.e. has no strong reference fields beyond
6310  * duk_hobject base header.  This is used just for asserts so doesn't need to
6311  * be optimized.
6312  */
6313 #define DUK_HOBJECT_PROHIBITS_FASTREFS(h) \
6314 	(DUK_HOBJECT_IS_COMPFUNC((h)) || DUK_HOBJECT_IS_DECENV((h)) || DUK_HOBJECT_IS_OBJENV((h)) || \
6315 	 DUK_HOBJECT_IS_BUFOBJ((h)) || DUK_HOBJECT_IS_THREAD((h)) || DUK_HOBJECT_IS_PROXY((h)) || \
6316 	 DUK_HOBJECT_IS_BOUNDFUNC((h)))
6317 #define DUK_HOBJECT_ALLOWS_FASTREFS(h) (!DUK_HOBJECT_PROHIBITS_FASTREFS((h)))
6318 
6319 /* Flags used for property attributes in duk_propdesc and packed flags.
6320  * Must fit into 8 bits.
6321  */
6322 #define DUK_PROPDESC_FLAG_WRITABLE              (1U << 0)    /* E5 Section 8.6.1 */
6323 #define DUK_PROPDESC_FLAG_ENUMERABLE            (1U << 1)    /* E5 Section 8.6.1 */
6324 #define DUK_PROPDESC_FLAG_CONFIGURABLE          (1U << 2)    /* E5 Section 8.6.1 */
6325 #define DUK_PROPDESC_FLAG_ACCESSOR              (1U << 3)    /* accessor */
6326 #define DUK_PROPDESC_FLAG_VIRTUAL               (1U << 4)    /* property is virtual: used in duk_propdesc, never stored
6327                                                              * (used by e.g. buffer virtual properties)
6328                                                              */
6329 #define DUK_PROPDESC_FLAGS_MASK                 (DUK_PROPDESC_FLAG_WRITABLE | \
6330                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6331                                                  DUK_PROPDESC_FLAG_CONFIGURABLE | \
6332                                                  DUK_PROPDESC_FLAG_ACCESSOR)
6333 
6334 /* Additional flags which are passed in the same flags argument as property
6335  * flags but are not stored in object properties.
6336  */
6337 #define DUK_PROPDESC_FLAG_NO_OVERWRITE          (1U << 4)    /* internal define property: skip write silently if exists */
6338 
6339 /* Convenience defines for property attributes. */
6340 #define DUK_PROPDESC_FLAGS_NONE                 0
6341 #define DUK_PROPDESC_FLAGS_W                    (DUK_PROPDESC_FLAG_WRITABLE)
6342 #define DUK_PROPDESC_FLAGS_E                    (DUK_PROPDESC_FLAG_ENUMERABLE)
6343 #define DUK_PROPDESC_FLAGS_C                    (DUK_PROPDESC_FLAG_CONFIGURABLE)
6344 #define DUK_PROPDESC_FLAGS_WE                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ENUMERABLE)
6345 #define DUK_PROPDESC_FLAGS_WC                   (DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6346 #define DUK_PROPDESC_FLAGS_EC                   (DUK_PROPDESC_FLAG_ENUMERABLE | DUK_PROPDESC_FLAG_CONFIGURABLE)
6347 #define DUK_PROPDESC_FLAGS_WEC                  (DUK_PROPDESC_FLAG_WRITABLE | \
6348                                                  DUK_PROPDESC_FLAG_ENUMERABLE | \
6349                                                  DUK_PROPDESC_FLAG_CONFIGURABLE)
6350 
6351 /* Flags for duk_hobject_get_own_propdesc() and variants. */
6352 #define DUK_GETDESC_FLAG_PUSH_VALUE          (1U << 0)  /* push value to stack */
6353 #define DUK_GETDESC_FLAG_IGNORE_PROTOLOOP    (1U << 1)  /* don't throw for prototype loop */
6354 
6355 /*
6356  *  Macro for object validity check
6357  *
6358  *  Assert for currently guaranteed relations between flags, for instance.
6359  */
6360 
6361 #define DUK_ASSERT_HOBJECT_VALID(h) do { \
6362 		DUK_ASSERT((h) != NULL); \
6363 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE((h)) || \
6364 		           DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FUNCTION); \
6365 		DUK_ASSERT(!DUK_HOBJECT_IS_BUFOBJ((h)) || \
6366 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAYBUFFER || \
6367 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_DATAVIEW || \
6368 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT8ARRAY || \
6369 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8ARRAY || \
6370 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY || \
6371 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT16ARRAY || \
6372 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT16ARRAY || \
6373 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_INT32ARRAY || \
6374 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_UINT32ARRAY || \
6375 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT32ARRAY || \
6376 		            DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_FLOAT64ARRAY)); \
6377 		/* Object is an Array <=> object has exotic array behavior */ \
6378 		DUK_ASSERT((DUK_HOBJECT_GET_CLASS_NUMBER((h)) == DUK_HOBJECT_CLASS_ARRAY && DUK_HOBJECT_HAS_EXOTIC_ARRAY((h))) || \
6379 		           (DUK_HOBJECT_GET_CLASS_NUMBER((h)) != DUK_HOBJECT_CLASS_ARRAY && !DUK_HOBJECT_HAS_EXOTIC_ARRAY((h)))); \
6380 	} while (0)
6381 
6382 /*
6383  *  Macros to access the 'props' allocation.
6384  */
6385 
6386 #if defined(DUK_USE_HEAPPTR16)
6387 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6388 	((duk_uint8_t *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (h))->h_extra16))
6389 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6390 		((duk_heaphdr *) (h))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6391 	} while (0)
6392 #else
6393 #define DUK_HOBJECT_GET_PROPS(heap,h) \
6394 	((h)->props)
6395 #define DUK_HOBJECT_SET_PROPS(heap,h,x) do { \
6396 		(h)->props = (duk_uint8_t *) (x); \
6397 	} while (0)
6398 #endif
6399 
6400 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
6401 /* LAYOUT 1 */
6402 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6403 	((duk_hstring **) (void *) ( \
6404 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6405 	))
6406 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6407 	((duk_propvalue *) (void *) ( \
6408 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6409 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_hstring *) \
6410 	))
6411 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6412 	((duk_uint8_t *) (void *) ( \
6413 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6414 	))
6415 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6416 	((duk_tval *) (void *) ( \
6417 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6418 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) \
6419 	))
6420 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6421 	((duk_uint32_t *) (void *) ( \
6422 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6423 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6424 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6425 	))
6426 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6427 	( \
6428 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6429 		(n_arr) * sizeof(duk_tval) + \
6430 		(n_hash) * sizeof(duk_uint32_t) \
6431 	)
6432 #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 { \
6433 		(set_e_k) = (duk_hstring **) (void *) (p_base); \
6434 		(set_e_pv) = (duk_propvalue *) (void *) ((set_e_k) + (n_ent)); \
6435 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_pv) + (n_ent)); \
6436 		(set_a) = (duk_tval *) (void *) ((set_e_f) + (n_ent)); \
6437 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6438 	} while (0)
6439 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
6440 /* LAYOUT 2 */
6441 #if (DUK_USE_ALIGN_BY == 4)
6442 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((4 - (e_sz)) & 0x03)
6443 #elif (DUK_USE_ALIGN_BY == 8)
6444 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) ((8 - (e_sz)) & 0x07)
6445 #elif (DUK_USE_ALIGN_BY == 1)
6446 #define DUK_HOBJECT_E_FLAG_PADDING(e_sz) 0
6447 #else
6448 #error invalid DUK_USE_ALIGN_BY
6449 #endif
6450 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6451 	((duk_hstring **) (void *) ( \
6452 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6453 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6454 	))
6455 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6456 	((duk_propvalue *) (void *) ( \
6457 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6458 	))
6459 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6460 	((duk_uint8_t *) (void *) ( \
6461 		DUK_HOBJECT_GET_PROPS((heap), (h)) + DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue)) \
6462 	))
6463 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6464 	((duk_tval *) (void *) ( \
6465 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6466 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6467 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) \
6468 	))
6469 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6470 	((duk_uint32_t *) (void *) ( \
6471 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6472 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6473 			DUK_HOBJECT_E_FLAG_PADDING(DUK_HOBJECT_GET_ESIZE((h))) + \
6474 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6475 	))
6476 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6477 	( \
6478 		(n_ent) * (sizeof(duk_hstring *) + sizeof(duk_propvalue) + sizeof(duk_uint8_t)) + \
6479 		DUK_HOBJECT_E_FLAG_PADDING((n_ent)) + \
6480 		(n_arr) * sizeof(duk_tval) + \
6481 		(n_hash) * sizeof(duk_uint32_t) \
6482 	)
6483 #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 { \
6484 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6485 		(set_e_k) = (duk_hstring **) (void *) ((set_e_pv) + (n_ent)); \
6486 		(set_e_f) = (duk_uint8_t *) (void *) ((set_e_k) + (n_ent)); \
6487 		(set_a) = (duk_tval *) (void *) (((duk_uint8_t *) (set_e_f)) + \
6488 		                                 sizeof(duk_uint8_t) * (n_ent) + \
6489 		                                 DUK_HOBJECT_E_FLAG_PADDING((n_ent))); \
6490 		(set_h) = (duk_uint32_t *) (void *) ((set_a) + (n_arr)); \
6491 	} while (0)
6492 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
6493 /* LAYOUT 3 */
6494 #define DUK_HOBJECT_E_GET_KEY_BASE(heap,h) \
6495 	((duk_hstring **) (void *) ( \
6496 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6497 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) + \
6498 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6499 	))
6500 #define DUK_HOBJECT_E_GET_VALUE_BASE(heap,h) \
6501 	((duk_propvalue *) (void *) ( \
6502 		DUK_HOBJECT_GET_PROPS((heap), (h)) \
6503 	))
6504 #define DUK_HOBJECT_E_GET_FLAGS_BASE(heap,h) \
6505 	((duk_uint8_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 			DUK_HOBJECT_GET_HSIZE((h)) * sizeof(duk_uint32_t) \
6510 	))
6511 #define DUK_HOBJECT_A_GET_BASE(heap,h) \
6512 	((duk_tval *) (void *) ( \
6513 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6514 			DUK_HOBJECT_GET_ESIZE((h)) * sizeof(duk_propvalue) \
6515 	))
6516 #define DUK_HOBJECT_H_GET_BASE(heap,h) \
6517 	((duk_uint32_t *) (void *) ( \
6518 		DUK_HOBJECT_GET_PROPS((heap), (h)) + \
6519 			DUK_HOBJECT_GET_ESIZE((h)) * (sizeof(duk_propvalue) + sizeof(duk_hstring *)) + \
6520 			DUK_HOBJECT_GET_ASIZE((h)) * sizeof(duk_tval) \
6521 	))
6522 #define DUK_HOBJECT_P_COMPUTE_SIZE(n_ent,n_arr,n_hash) \
6523 	( \
6524 		(n_ent) * (sizeof(duk_propvalue) + sizeof(duk_hstring *) + sizeof(duk_uint8_t)) + \
6525 		(n_arr) * sizeof(duk_tval) + \
6526 		(n_hash) * sizeof(duk_uint32_t) \
6527 	)
6528 #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 { \
6529 		(set_e_pv) = (duk_propvalue *) (void *) (p_base); \
6530 		(set_a) = (duk_tval *) (void *) ((set_e_pv) + (n_ent)); \
6531 		(set_e_k) = (duk_hstring **) (void *) ((set_a) + (n_arr)); \
6532 		(set_h) = (duk_uint32_t *) (void *) ((set_e_k) + (n_ent)); \
6533 		(set_e_f) = (duk_uint8_t *) (void *) ((set_h) + (n_hash)); \
6534 	} while (0)
6535 #else
6536 #error invalid hobject layout defines
6537 #endif  /* hobject property layout */
6538 
6539 #define DUK_HOBJECT_P_ALLOC_SIZE(h) \
6540 	DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE((h)), DUK_HOBJECT_GET_ASIZE((h)), DUK_HOBJECT_GET_HSIZE((h)))
6541 
6542 #define DUK_HOBJECT_E_GET_KEY(heap,h,i)              (DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6543 #define DUK_HOBJECT_E_GET_KEY_PTR(heap,h,i)          (&DUK_HOBJECT_E_GET_KEY_BASE((heap), (h))[(i)])
6544 #define DUK_HOBJECT_E_GET_VALUE(heap,h,i)            (DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6545 #define DUK_HOBJECT_E_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_VALUE_BASE((heap), (h))[(i)])
6546 #define DUK_HOBJECT_E_GET_VALUE_TVAL(heap,h,i)       (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6547 #define DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap,h,i)   (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v)
6548 #define DUK_HOBJECT_E_GET_VALUE_GETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6549 #define DUK_HOBJECT_E_GET_VALUE_GETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get)
6550 #define DUK_HOBJECT_E_GET_VALUE_SETTER(heap,h,i)     (DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6551 #define DUK_HOBJECT_E_GET_VALUE_SETTER_PTR(heap,h,i) (&DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set)
6552 #define DUK_HOBJECT_E_GET_FLAGS(heap,h,i)            (DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6553 #define DUK_HOBJECT_E_GET_FLAGS_PTR(heap,h,i)        (&DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)])
6554 #define DUK_HOBJECT_A_GET_VALUE(heap,h,i)            (DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6555 #define DUK_HOBJECT_A_GET_VALUE_PTR(heap,h,i)        (&DUK_HOBJECT_A_GET_BASE((heap), (h))[(i)])
6556 #define DUK_HOBJECT_H_GET_INDEX(heap,h,i)            (DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6557 #define DUK_HOBJECT_H_GET_INDEX_PTR(heap,h,i)        (&DUK_HOBJECT_H_GET_BASE((heap), (h))[(i)])
6558 
6559 #define DUK_HOBJECT_E_SET_KEY(heap,h,i,k)  do { \
6560 		DUK_HOBJECT_E_GET_KEY((heap), (h), (i)) = (k); \
6561 	} while (0)
6562 #define DUK_HOBJECT_E_SET_VALUE(heap,h,i,v)  do { \
6563 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)) = (v); \
6564 	} while (0)
6565 #define DUK_HOBJECT_E_SET_VALUE_TVAL(heap,h,i,v)  do { \
6566 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).v = (v); \
6567 	} while (0)
6568 #define DUK_HOBJECT_E_SET_VALUE_GETTER(heap,h,i,v)  do { \
6569 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.get = (v); \
6570 	} while (0)
6571 #define DUK_HOBJECT_E_SET_VALUE_SETTER(heap,h,i,v)  do { \
6572 		DUK_HOBJECT_E_GET_VALUE((heap), (h), (i)).a.set = (v); \
6573 	} while (0)
6574 #define DUK_HOBJECT_E_SET_FLAGS(heap,h,i,f)  do { \
6575 		DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) = (duk_uint8_t) (f); \
6576 	} while (0)
6577 #define DUK_HOBJECT_A_SET_VALUE(heap,h,i,v)  do { \
6578 		DUK_HOBJECT_A_GET_VALUE((heap), (h), (i)) = (v); \
6579 	} while (0)
6580 #define DUK_HOBJECT_A_SET_VALUE_TVAL(heap,h,i,v) \
6581 	DUK_HOBJECT_A_SET_VALUE((heap), (h), (i), (v))  /* alias for above */
6582 #define DUK_HOBJECT_H_SET_INDEX(heap,h,i,v)  do { \
6583 		DUK_HOBJECT_H_GET_INDEX((heap), (h), (i)) = (v); \
6584 	} while (0)
6585 
6586 #define DUK_HOBJECT_E_SET_FLAG_BITS(heap,h,i,mask)  do { \
6587 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] |= (mask); \
6588 	} while (0)
6589 
6590 #define DUK_HOBJECT_E_CLEAR_FLAG_BITS(heap,h,i,mask)  do { \
6591 		DUK_HOBJECT_E_GET_FLAGS_BASE((heap), (h))[(i)] &= ~(mask); \
6592 	} while (0)
6593 
6594 #define DUK_HOBJECT_E_SLOT_IS_WRITABLE(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6595 #define DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(heap,h,i)   ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6596 #define DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(heap,h,i) ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6597 #define DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap,h,i)     ((DUK_HOBJECT_E_GET_FLAGS((heap), (h), (i)) & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6598 
6599 #define DUK_HOBJECT_E_SLOT_SET_WRITABLE(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6600 #define DUK_HOBJECT_E_SLOT_SET_ENUMERABLE(heap,h,i)      DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6601 #define DUK_HOBJECT_E_SLOT_SET_CONFIGURABLE(heap,h,i)    DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6602 #define DUK_HOBJECT_E_SLOT_SET_ACCESSOR(heap,h,i)        DUK_HOBJECT_E_SET_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6603 
6604 #define DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_WRITABLE)
6605 #define DUK_HOBJECT_E_SLOT_CLEAR_ENUMERABLE(heap,h,i)    DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ENUMERABLE)
6606 #define DUK_HOBJECT_E_SLOT_CLEAR_CONFIGURABLE(heap,h,i)  DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_CONFIGURABLE)
6607 #define DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(heap,h,i)      DUK_HOBJECT_E_CLEAR_FLAG_BITS((heap), (h), (i),DUK_PROPDESC_FLAG_ACCESSOR)
6608 
6609 #define DUK_PROPDESC_IS_WRITABLE(p)             (((p)->flags & DUK_PROPDESC_FLAG_WRITABLE) != 0)
6610 #define DUK_PROPDESC_IS_ENUMERABLE(p)           (((p)->flags & DUK_PROPDESC_FLAG_ENUMERABLE) != 0)
6611 #define DUK_PROPDESC_IS_CONFIGURABLE(p)         (((p)->flags & DUK_PROPDESC_FLAG_CONFIGURABLE) != 0)
6612 #define DUK_PROPDESC_IS_ACCESSOR(p)             (((p)->flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0)
6613 
6614 #define DUK_HOBJECT_HASHIDX_UNUSED              0xffffffffUL
6615 #define DUK_HOBJECT_HASHIDX_DELETED             0xfffffffeUL
6616 
6617 /*
6618  *  Macros for accessing size fields
6619  */
6620 
6621 #if defined(DUK_USE_OBJSIZES16)
6622 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size16)
6623 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size16 = (v); } while (0)
6624 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next16)
6625 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next16 = (v); } while (0)
6626 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next16++)
6627 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size16)
6628 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size16 = (v); } while (0)
6629 #if defined(DUK_USE_HOBJECT_HASH_PART)
6630 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size16)
6631 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size16 = (v); } while (0)
6632 #else
6633 #define DUK_HOBJECT_GET_HSIZE(h) 0
6634 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6635 #endif
6636 #else
6637 #define DUK_HOBJECT_GET_ESIZE(h) ((h)->e_size)
6638 #define DUK_HOBJECT_SET_ESIZE(h,v) do { (h)->e_size = (v); } while (0)
6639 #define DUK_HOBJECT_GET_ENEXT(h) ((h)->e_next)
6640 #define DUK_HOBJECT_SET_ENEXT(h,v) do { (h)->e_next = (v); } while (0)
6641 #define DUK_HOBJECT_POSTINC_ENEXT(h) ((h)->e_next++)
6642 #define DUK_HOBJECT_GET_ASIZE(h) ((h)->a_size)
6643 #define DUK_HOBJECT_SET_ASIZE(h,v) do { (h)->a_size = (v); } while (0)
6644 #if defined(DUK_USE_HOBJECT_HASH_PART)
6645 #define DUK_HOBJECT_GET_HSIZE(h) ((h)->h_size)
6646 #define DUK_HOBJECT_SET_HSIZE(h,v) do { (h)->h_size = (v); } while (0)
6647 #else
6648 #define DUK_HOBJECT_GET_HSIZE(h) 0
6649 #define DUK_HOBJECT_SET_HSIZE(h,v) do { DUK_ASSERT((v) == 0); } while (0)
6650 #endif
6651 #endif
6652 
6653 /*
6654  *  Misc
6655  */
6656 
6657 /* Maximum prototype traversal depth.  Sanity limit which handles e.g.
6658  * prototype loops (even complex ones like 1->2->3->4->2->3->4->2->3->4).
6659  */
6660 #define DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY      10000L
6661 
6662 /*
6663  *  ECMAScript [[Class]]
6664  */
6665 
6666 /* range check not necessary because all 4-bit values are mapped */
6667 #define DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(n)  duk_class_number_to_stridx[(n)]
6668 
6669 #define DUK_HOBJECT_GET_CLASS_STRING(heap,h)          \
6670 	DUK_HEAP_GET_STRING( \
6671 		(heap), \
6672 		DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(DUK_HOBJECT_GET_CLASS_NUMBER((h))) \
6673 	)
6674 
6675 /*
6676  *  Macros for property handling
6677  */
6678 
6679 #if defined(DUK_USE_HEAPPTR16)
6680 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6681 	((duk_hobject *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->prototype16))
6682 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6683 		(h)->prototype16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (x)); \
6684 	} while (0)
6685 #else
6686 #define DUK_HOBJECT_GET_PROTOTYPE(heap,h) \
6687 	((h)->prototype)
6688 #define DUK_HOBJECT_SET_PROTOTYPE(heap,h,x) do { \
6689 		(h)->prototype = (x); \
6690 	} while (0)
6691 #endif
6692 
6693 /* Set prototype, DECREF earlier value, INCREF new value (tolerating NULLs). */
6694 #define DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr,h,p)       duk_hobject_set_prototype_updref((thr), (h), (p))
6695 
6696 /* Set initial prototype, assume NULL previous prototype, INCREF new value,
6697  * tolerate NULL.
6698  */
6699 #define DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr,h,proto) do { \
6700 		duk_hthread *duk__thr = (thr); \
6701 		duk_hobject *duk__obj = (h); \
6702 		duk_hobject *duk__proto = (proto); \
6703 		DUK_UNREF(duk__thr); \
6704 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(duk__thr->heap, duk__obj) == NULL); \
6705 		DUK_HOBJECT_SET_PROTOTYPE(duk__thr->heap, duk__obj, duk__proto); \
6706 		DUK_HOBJECT_INCREF_ALLOWNULL(duk__thr, duk__proto); \
6707 	} while (0)
6708 
6709 /*
6710  *  Finalizer check
6711  */
6712 
6713 #if defined(DUK_USE_HEAPPTR16)
6714 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((heap), (h))
6715 #else
6716 #define DUK_HOBJECT_HAS_FINALIZER_FAST(heap,h) duk_hobject_has_finalizer_fast_raw((h))
6717 #endif
6718 
6719 /*
6720  *  Resizing and hash behavior
6721  */
6722 
6723 /* Sanity limit on max number of properties (allocated, not necessarily used).
6724  * This is somewhat arbitrary, but if we're close to 2**32 properties some
6725  * algorithms will fail (e.g. hash size selection, next prime selection).
6726  * Also, we use negative array/entry table indices to indicate 'not found',
6727  * so anything above 0x80000000 will cause trouble now.
6728  */
6729 #if defined(DUK_USE_OBJSIZES16)
6730 #define DUK_HOBJECT_MAX_PROPERTIES       0x0000ffffUL
6731 #else
6732 #define DUK_HOBJECT_MAX_PROPERTIES       0x3fffffffUL   /* 2**30-1 ~= 1G properties */
6733 #endif
6734 
6735 /* internal align target for props allocation, must be 2*n for some n */
6736 #if (DUK_USE_ALIGN_BY == 4)
6737 #define DUK_HOBJECT_ALIGN_TARGET         4
6738 #elif (DUK_USE_ALIGN_BY == 8)
6739 #define DUK_HOBJECT_ALIGN_TARGET         8
6740 #elif (DUK_USE_ALIGN_BY == 1)
6741 #define DUK_HOBJECT_ALIGN_TARGET         1
6742 #else
6743 #error invalid DUK_USE_ALIGN_BY
6744 #endif
6745 
6746 /*
6747  *  PC-to-line constants
6748  */
6749 
6750 #define DUK_PC2LINE_SKIP    64
6751 
6752 /* maximum length for a SKIP-1 diffstream: 35 bits per entry, rounded up to bytes */
6753 #define DUK_PC2LINE_MAX_DIFF_LENGTH    (((DUK_PC2LINE_SKIP - 1) * 35 + 7) / 8)
6754 
6755 /*
6756  *  Struct defs
6757  */
6758 
6759 struct duk_propaccessor {
6760 	duk_hobject *get;
6761 	duk_hobject *set;
6762 };
6763 
6764 union duk_propvalue {
6765 	/* The get/set pointers could be 16-bit pointer compressed but it
6766 	 * would make no difference on 32-bit platforms because duk_tval is
6767 	 * 8 bytes or more anyway.
6768 	 */
6769 	duk_tval v;
6770 	duk_propaccessor a;
6771 };
6772 
6773 struct duk_propdesc {
6774 	/* read-only values 'lifted' for ease of use */
6775 	duk_small_uint_t flags;
6776 	duk_hobject *get;
6777 	duk_hobject *set;
6778 
6779 	/* for updating (all are set to < 0 for virtual properties) */
6780 	duk_int_t e_idx;  /* prop index in 'entry part', < 0 if not there */
6781 	duk_int_t h_idx;  /* prop index in 'hash part', < 0 if not there */
6782 	duk_int_t a_idx;  /* prop index in 'array part', < 0 if not there */
6783 };
6784 
6785 struct duk_hobject {
6786 	duk_heaphdr hdr;
6787 
6788 	/*
6789 	 *  'props' contains {key,value,flags} entries, optional array entries, and
6790 	 *  an optional hash lookup table for non-array entries in a single 'sliced'
6791 	 *  allocation.  There are several layout options, which differ slightly in
6792 	 *  generated code size/speed and alignment/padding; duk_features.h selects
6793 	 *  the layout used.
6794 	 *
6795 	 *  Layout 1 (DUK_USE_HOBJECT_LAYOUT_1):
6796 	 *
6797 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6798 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6799 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6800 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6801 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6802 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6803 	 *
6804 	 *  Layout 2 (DUK_USE_HOBJECT_LAYOUT_2):
6805 	 *
6806 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6807 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6808 	 *    e_size * sizeof(duk_uint8_t) + pad     bytes of   entry flags (e_next gc reachable)
6809 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6810 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6811 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6812 	 *
6813 	 *  Layout 3 (DUK_USE_HOBJECT_LAYOUT_3):
6814 	 *
6815 	 *    e_size * sizeof(duk_propvalue)         bytes of   entry values (e_next gc reachable)
6816 	 *    a_size * sizeof(duk_tval)              bytes of   (opt) array values (plain only) (all gc reachable)
6817 	 *    e_size * sizeof(duk_hstring *)         bytes of   entry keys (e_next gc reachable)
6818 	 *    h_size * sizeof(duk_uint32_t)          bytes of   (opt) hash indexes to entries (e_size),
6819 	 *                                                      0xffffffffUL = unused, 0xfffffffeUL = deleted
6820 	 *    e_size * sizeof(duk_uint8_t)           bytes of   entry flags (e_next gc reachable)
6821 	 *
6822 	 *  In layout 1, the 'e_next' count is rounded to 4 or 8 on platforms
6823 	 *  requiring 4 or 8 byte alignment.  This ensures proper alignment
6824 	 *  for the entries, at the cost of memory footprint.  However, it's
6825 	 *  probably preferable to use another layout on such platforms instead.
6826 	 *
6827 	 *  In layout 2, the key and value parts are swapped to avoid padding
6828 	 *  the key array on platforms requiring alignment by 8.  The flags part
6829 	 *  is padded to get alignment for array entries.  The 'e_next' count does
6830 	 *  not need to be rounded as in layout 1.
6831 	 *
6832 	 *  In layout 3, entry values and array values are always aligned properly,
6833 	 *  and assuming pointers are at most 8 bytes, so are the entry keys.  Hash
6834 	 *  indices will be properly aligned (assuming pointers are at least 4 bytes).
6835 	 *  Finally, flags don't need additional alignment.  This layout provides
6836 	 *  compact allocations without padding (even on platforms with alignment
6837 	 *  requirements) at the cost of a bit slower lookups.
6838 	 *
6839 	 *  Objects with few keys don't have a hash index; keys are looked up linearly,
6840 	 *  which is cache efficient because the keys are consecutive.  Larger objects
6841 	 *  have a hash index part which contains integer indexes to the entries part.
6842 	 *
6843 	 *  A single allocation reduces memory allocation overhead but requires more
6844 	 *  work when any part needs to be resized.  A sliced allocation for entries
6845 	 *  makes linear key matching faster on most platforms (more locality) and
6846 	 *  skimps on flags size (which would be followed by 3 bytes of padding in
6847 	 *  most architectures if entries were placed in a struct).
6848 	 *
6849 	 *  'props' also contains internal properties distinguished with a non-BMP
6850 	 *  prefix.  Often used properties should be placed early in 'props' whenever
6851 	 *  possible to make accessing them as fast a possible.
6852 	 */
6853 
6854 #if defined(DUK_USE_HEAPPTR16)
6855 	/* Located in duk_heaphdr h_extra16.  Subclasses of duk_hobject (like
6856 	 * duk_hcompfunc) are not free to use h_extra16 for this reason.
6857 	 */
6858 #else
6859 	duk_uint8_t *props;
6860 #endif
6861 
6862 	/* prototype: the only internal property lifted outside 'e' as it is so central */
6863 #if defined(DUK_USE_HEAPPTR16)
6864 	duk_uint16_t prototype16;
6865 #else
6866 	duk_hobject *prototype;
6867 #endif
6868 
6869 #if defined(DUK_USE_OBJSIZES16)
6870 	duk_uint16_t e_size16;
6871 	duk_uint16_t e_next16;
6872 	duk_uint16_t a_size16;
6873 #if defined(DUK_USE_HOBJECT_HASH_PART)
6874 	duk_uint16_t h_size16;
6875 #endif
6876 #else
6877 	duk_uint32_t e_size;  /* entry part size */
6878 	duk_uint32_t e_next;  /* index for next new key ([0,e_next[ are gc reachable) */
6879 	duk_uint32_t a_size;  /* array part size (entirely gc reachable) */
6880 #if defined(DUK_USE_HOBJECT_HASH_PART)
6881 	duk_uint32_t h_size;  /* hash part size or 0 if unused */
6882 #endif
6883 #endif
6884 };
6885 
6886 /*
6887  *  Exposed data
6888  */
6889 
6890 #if !defined(DUK_SINGLE_FILE)
6891 DUK_INTERNAL_DECL duk_uint8_t duk_class_number_to_stridx[32];
6892 #endif  /* !DUK_SINGLE_FILE */
6893 
6894 /*
6895  *  Prototypes
6896  */
6897 
6898 /* alloc and init */
6899 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6900 DUK_INTERNAL_DECL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6901 DUK_INTERNAL_DECL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6902 DUK_INTERNAL_DECL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6903 DUK_INTERNAL_DECL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6904 DUK_INTERNAL_DECL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags);
6905 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
6906 DUK_INTERNAL_DECL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6907 #endif
6908 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags);
6909 DUK_INTERNAL_DECL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6910 DUK_INTERNAL_DECL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6911 DUK_INTERNAL_DECL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6912 DUK_INTERNAL_DECL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags);
6913 
6914 /* resize */
6915 DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
6916                                                  duk_hobject *obj,
6917                                                  duk_uint32_t new_e_size,
6918                                                  duk_uint32_t new_a_size,
6919                                                  duk_uint32_t new_h_size,
6920                                                  duk_bool_t abandon_array);
6921 DUK_INTERNAL_DECL void duk_hobject_resize_entrypart(duk_hthread *thr,
6922                                                     duk_hobject *obj,
6923                                                     duk_uint32_t new_e_size);
6924 #if 0  /*unused*/
6925 DUK_INTERNAL_DECL void duk_hobject_resize_arraypart(duk_hthread *thr,
6926                                                     duk_hobject *obj,
6927                                                     duk_uint32_t new_a_size);
6928 #endif
6929 
6930 /* low-level property functions */
6931 DUK_INTERNAL_DECL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
6932 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key);
6933 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs);
6934 DUK_INTERNAL_DECL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i);
6935 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);
6936 
6937 /* XXX: when optimizing for guaranteed property slots, use a guaranteed
6938  * slot for internal value; this call can then access it directly.
6939  */
6940 #define duk_hobject_get_internal_value_tval_ptr(heap,obj) \
6941 	duk_hobject_find_existing_entry_tval_ptr((heap), (obj), DUK_HEAP_STRING_INT_VALUE((heap)))
6942 
6943 /* core property functions */
6944 DUK_INTERNAL_DECL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6945 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);
6946 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);
6947 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key);
6948 
6949 /* internal property functions */
6950 #define DUK_DELPROP_FLAG_THROW  (1U << 0)
6951 #define DUK_DELPROP_FLAG_FORCE  (1U << 1)
6952 DUK_INTERNAL_DECL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6953 DUK_INTERNAL_DECL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key);
6954 DUK_INTERNAL_DECL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags);
6955 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);
6956 DUK_INTERNAL_DECL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj);
6957 #if defined(DUK_USE_HEAPPTR16)
6958 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj);
6959 #else
6960 DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj);
6961 #endif
6962 
6963 /* helpers for defineProperty() and defineProperties() */
6964 DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
6965                                                                duk_idx_t idx_in,
6966                                                                duk_uint_t *out_defprop_flags,
6967                                                                duk_idx_t *out_idx_value,
6968                                                                duk_hobject **out_getter,
6969                                                                duk_hobject **out_setter);
6970 DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
6971                                                                 duk_uint_t defprop_flags,
6972                                                                 duk_hobject *obj,
6973                                                                 duk_hstring *key,
6974                                                                 duk_idx_t idx_value,
6975                                                                 duk_hobject *get,
6976                                                                 duk_hobject *set,
6977                                                                 duk_bool_t throw_flag);
6978 
6979 /* Object built-in methods */
6980 DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx);
6981 DUK_INTERNAL_DECL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze);
6982 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen);
6983 DUK_INTERNAL_DECL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags);
6984 
6985 /* internal properties */
6986 DUK_INTERNAL_DECL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv);
6987 DUK_INTERNAL_DECL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj);
6988 
6989 /* hobject management functions */
6990 DUK_INTERNAL_DECL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj);
6991 
6992 /* ES2015 proxy */
6993 #if defined(DUK_USE_ES6_PROXY)
6994 DUK_INTERNAL_DECL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler);
6995 DUK_INTERNAL_DECL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj);
6996 #endif
6997 
6998 /* enumeration */
6999 DUK_INTERNAL_DECL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags);
7000 DUK_INTERNAL_DECL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags);
7001 DUK_INTERNAL_DECL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value);
7002 
7003 /* macros */
7004 DUK_INTERNAL_DECL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p);
7005 
7006 /* pc2line */
7007 #if defined(DUK_USE_PC2LINE)
7008 DUK_INTERNAL_DECL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length);
7009 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc);
7010 #endif
7011 
7012 /* misc */
7013 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);
7014 
7015 #if !defined(DUK_USE_OBJECT_BUILTIN)
7016 /* These declarations are needed when related built-in is disabled and
7017  * genbuiltins.py won't automatically emit the declerations.
7018  */
7019 DUK_INTERNAL_DECL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr);
7020 DUK_INTERNAL_DECL duk_ret_t duk_bi_function_prototype(duk_hthread *thr);
7021 #endif
7022 
7023 #endif  /* DUK_HOBJECT_H_INCLUDED */
7024 /* #include duk_hcompfunc.h */
7025 #line 1 "duk_hcompfunc.h"
7026 /*
7027  *  Heap compiled function (ECMAScript function) representation.
7028  *
7029  *  There is a single data buffer containing the ECMAScript function's
7030  *  bytecode, constants, and inner functions.
7031  */
7032 
7033 #if !defined(DUK_HCOMPFUNC_H_INCLUDED)
7034 #define DUK_HCOMPFUNC_H_INCLUDED
7035 
7036 /*
7037  *  Field accessor macros
7038  */
7039 
7040 /* XXX: casts could be improved, especially for GET/SET DATA */
7041 
7042 #if defined(DUK_USE_HEAPPTR16)
7043 #define DUK_HCOMPFUNC_GET_DATA(heap,h) \
7044 	((duk_hbuffer_fixed *) (void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->data16))
7045 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7046 		(h)->data16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7047 	} while (0)
7048 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  \
7049 	((duk_hobject **) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->funcs16)))
7050 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7051 		(h)->funcs16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7052 	} while (0)
7053 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  \
7054 	((duk_instr_t *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->bytecode16)))
7055 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7056 		(h)->bytecode16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7057 	} while (0)
7058 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  \
7059 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->lex_env16)))
7060 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7061 		(h)->lex_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7062 	} while (0)
7063 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  \
7064 	((duk_hobject *) (void *) (DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (h)->var_env16)))
7065 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7066 		(h)->var_env16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
7067 	} while (0)
7068 #else
7069 #define DUK_HCOMPFUNC_GET_DATA(heap,h)  ((duk_hbuffer_fixed *) (void *) (h)->data)
7070 #define DUK_HCOMPFUNC_SET_DATA(heap,h,v) do { \
7071 		(h)->data = (duk_hbuffer *) (v); \
7072 	} while (0)
7073 #define DUK_HCOMPFUNC_GET_FUNCS(heap,h)  ((h)->funcs)
7074 #define DUK_HCOMPFUNC_SET_FUNCS(heap,h,v)  do { \
7075 		(h)->funcs = (v); \
7076 	} while (0)
7077 #define DUK_HCOMPFUNC_GET_BYTECODE(heap,h)  ((h)->bytecode)
7078 #define DUK_HCOMPFUNC_SET_BYTECODE(heap,h,v)  do { \
7079 		(h)->bytecode = (v); \
7080 	} while (0)
7081 #define DUK_HCOMPFUNC_GET_LEXENV(heap,h)  ((h)->lex_env)
7082 #define DUK_HCOMPFUNC_SET_LEXENV(heap,h,v)  do { \
7083 		(h)->lex_env = (v); \
7084 	} while (0)
7085 #define DUK_HCOMPFUNC_GET_VARENV(heap,h)  ((h)->var_env)
7086 #define DUK_HCOMPFUNC_SET_VARENV(heap,h,v)  do { \
7087 		(h)->var_env = (v); \
7088 	} while (0)
7089 #endif
7090 
7091 /*
7092  *  Accessor macros for function specific data areas
7093  */
7094 
7095 /* Note: assumes 'data' is always a fixed buffer */
7096 #define DUK_HCOMPFUNC_GET_BUFFER_BASE(heap,h)  \
7097 	DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h)))
7098 
7099 #define DUK_HCOMPFUNC_GET_CONSTS_BASE(heap,h)  \
7100 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_BUFFER_BASE((heap), (h)))
7101 
7102 #define DUK_HCOMPFUNC_GET_FUNCS_BASE(heap,h)  \
7103 	DUK_HCOMPFUNC_GET_FUNCS((heap), (h))
7104 
7105 #define DUK_HCOMPFUNC_GET_CODE_BASE(heap,h)  \
7106 	DUK_HCOMPFUNC_GET_BYTECODE((heap), (h))
7107 
7108 #define DUK_HCOMPFUNC_GET_CONSTS_END(heap,h)  \
7109 	((duk_tval *) (void *) DUK_HCOMPFUNC_GET_FUNCS((heap), (h)))
7110 
7111 #define DUK_HCOMPFUNC_GET_FUNCS_END(heap,h)  \
7112 	((duk_hobject **) (void *) DUK_HCOMPFUNC_GET_BYTECODE((heap), (h)))
7113 
7114 /* XXX: double evaluation of DUK_HCOMPFUNC_GET_DATA() */
7115 #define DUK_HCOMPFUNC_GET_CODE_END(heap,h)  \
7116 	((duk_instr_t *) (void *) (DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), DUK_HCOMPFUNC_GET_DATA((heap), (h))) + \
7117 	                DUK_HBUFFER_GET_SIZE((duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA((heap), h))))
7118 
7119 #define DUK_HCOMPFUNC_GET_CONSTS_SIZE(heap,h)  \
7120 	( \
7121 	 (duk_size_t) \
7122 	 ( \
7123 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_END((heap), (h))) - \
7124 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CONSTS_BASE((heap), (h))) \
7125 	 ) \
7126 	)
7127 
7128 #define DUK_HCOMPFUNC_GET_FUNCS_SIZE(heap,h)  \
7129 	( \
7130 	 (duk_size_t) \
7131 	 ( \
7132 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_END((heap), (h))) - \
7133 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_FUNCS_BASE((heap), (h))) \
7134 	 ) \
7135 	)
7136 
7137 #define DUK_HCOMPFUNC_GET_CODE_SIZE(heap,h)  \
7138 	( \
7139 	 (duk_size_t) \
7140 	 ( \
7141 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_END((heap),(h))) - \
7142 	   ((const duk_uint8_t *) DUK_HCOMPFUNC_GET_CODE_BASE((heap),(h))) \
7143 	 ) \
7144 	)
7145 
7146 #define DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap,h)  \
7147 	((duk_size_t) (DUK_HCOMPFUNC_GET_CONSTS_SIZE((heap), (h)) / sizeof(duk_tval)))
7148 
7149 #define DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap,h)  \
7150 	((duk_size_t) (DUK_HCOMPFUNC_GET_FUNCS_SIZE((heap), (h)) / sizeof(duk_hobject *)))
7151 
7152 #define DUK_HCOMPFUNC_GET_CODE_COUNT(heap,h)  \
7153 	((duk_size_t) (DUK_HCOMPFUNC_GET_CODE_SIZE((heap), (h)) / sizeof(duk_instr_t)))
7154 
7155 /*
7156  *  Validity assert
7157  */
7158 
7159 #define DUK_ASSERT_HCOMPFUNC_VALID(h) do { \
7160 		DUK_ASSERT((h) != NULL); \
7161 	} while (0)
7162 
7163 /*
7164  *  Main struct
7165  */
7166 
7167 struct duk_hcompfunc {
7168 	/* shared object part */
7169 	duk_hobject obj;
7170 
7171 	/*
7172 	 *  Pointers to function data area for faster access.  Function
7173 	 *  data is a buffer shared between all closures of the same
7174 	 *  "template" function.  The data buffer is always fixed (non-
7175 	 *  dynamic, hence stable), with a layout as follows:
7176 	 *
7177 	 *    constants (duk_tval)
7178 	 *    inner functions (duk_hobject *)
7179 	 *    bytecode (duk_instr_t)
7180 	 *
7181 	 *  Note: bytecode end address can be computed from 'data' buffer
7182 	 *  size.  It is not strictly necessary functionally, assuming
7183 	 *  bytecode never jumps outside its allocated area.  However,
7184 	 *  it's a safety/robustness feature for avoiding the chance of
7185 	 *  executing random data as bytecode due to a compiler error.
7186 	 *
7187 	 *  Note: values in the data buffer must be incref'd (they will
7188 	 *  be decref'd on release) for every compiledfunction referring
7189 	 *  to the 'data' element.
7190 	 */
7191 
7192 	/* Data area, fixed allocation, stable data ptrs. */
7193 #if defined(DUK_USE_HEAPPTR16)
7194 	duk_uint16_t data16;
7195 #else
7196 	duk_hbuffer *data;
7197 #endif
7198 
7199 	/* No need for constants pointer (= same as data).
7200 	 *
7201 	 * When using 16-bit packing alignment to 4 is nice.  'funcs' will be
7202 	 * 4-byte aligned because 'constants' are duk_tvals.  For now the
7203 	 * inner function pointers are not compressed, so that 'bytecode' will
7204 	 * also be 4-byte aligned.
7205 	 */
7206 #if defined(DUK_USE_HEAPPTR16)
7207 	duk_uint16_t funcs16;
7208 	duk_uint16_t bytecode16;
7209 #else
7210 	duk_hobject **funcs;
7211 	duk_instr_t *bytecode;
7212 #endif
7213 
7214 	/* Lexenv: lexical environment of closure, NULL for templates.
7215 	 * Varenv: variable environment of closure, NULL for templates.
7216 	 */
7217 #if defined(DUK_USE_HEAPPTR16)
7218 	duk_uint16_t lex_env16;
7219 	duk_uint16_t var_env16;
7220 #else
7221 	duk_hobject *lex_env;
7222 	duk_hobject *var_env;
7223 #endif
7224 
7225 	/*
7226 	 *  'nregs' registers are allocated on function entry, at most 'nargs'
7227 	 *  are initialized to arguments, and the rest to undefined.  Arguments
7228 	 *  above 'nregs' are not mapped to registers.  All registers in the
7229 	 *  active stack range must be initialized because they are GC reachable.
7230 	 *  'nargs' is needed so that if the function is given more than 'nargs'
7231 	 *  arguments, the additional arguments do not 'clobber' registers
7232 	 *  beyond 'nregs' which must be consistently initialized to undefined.
7233 	 *
7234 	 *  Usually there is no need to know which registers are mapped to
7235 	 *  local variables.  Registers may be allocated to variable in any
7236 	 *  way (even including gaps).  However, a register-variable mapping
7237 	 *  must be the same for the duration of the function execution and
7238 	 *  the register cannot be used for anything else.
7239 	 *
7240 	 *  When looking up variables by name, the '_Varmap' map is used.
7241 	 *  When an activation closes, registers mapped to arguments are
7242 	 *  copied into the environment record based on the same map.  The
7243 	 *  reverse map (from register to variable) is not currently needed
7244 	 *  at run time, except for debugging, so it is not maintained.
7245 	 */
7246 
7247 	duk_uint16_t nregs;                /* regs to allocate */
7248 	duk_uint16_t nargs;                /* number of arguments allocated to regs */
7249 
7250 	/*
7251 	 *  Additional control information is placed into the object itself
7252 	 *  as internal properties to avoid unnecessary fields for the
7253 	 *  majority of functions.  The compiler tries to omit internal
7254 	 *  control fields when possible.
7255 	 *
7256 	 *  Function templates:
7257 	 *
7258 	 *    {
7259 	 *      name: "func",    // declaration, named function expressions
7260 	 *      fileName: <debug info for creating nice errors>
7261 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7262 	 *      _Formals: [ "arg1", "arg2" ],
7263 	 *      _Source: "function func(arg1, arg2) { ... }",
7264 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7265 	 *    }
7266 	 *
7267 	 *  Function instances:
7268 	 *
7269 	 *    {
7270 	 *      length: 2,
7271 	 *      prototype: { constructor: <func> },
7272 	 *      caller: <thrower>,
7273 	 *      arguments: <thrower>,
7274 	 *      name: "func",    // declaration, named function expressions
7275 	 *      fileName: <debug info for creating nice errors>
7276 	 *      _Varmap: { "arg1": 0, "arg2": 1, "varname": 2 },
7277 	 *      _Formals: [ "arg1", "arg2" ],
7278 	 *      _Source: "function func(arg1, arg2) { ... }",
7279 	 *      _Pc2line: <debug info for pc-to-line mapping>,
7280 	 *    }
7281 	 *
7282 	 *  More detailed description of these properties can be found
7283 	 *  in the documentation.
7284 	 */
7285 
7286 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7287 	/* Line number range for function.  Needed during debugging to
7288 	 * determine active breakpoints.
7289 	 */
7290 	duk_uint32_t start_line;
7291 	duk_uint32_t end_line;
7292 #endif
7293 };
7294 
7295 #endif  /* DUK_HCOMPFUNC_H_INCLUDED */
7296 /* #include duk_hnatfunc.h */
7297 #line 1 "duk_hnatfunc.h"
7298 /*
7299  *  Heap native function representation.
7300  */
7301 
7302 #if !defined(DUK_HNATFUNC_H_INCLUDED)
7303 #define DUK_HNATFUNC_H_INCLUDED
7304 
7305 #define DUK_HNATFUNC_NARGS_VARARGS  ((duk_int16_t) -1)
7306 #define DUK_HNATFUNC_NARGS_MAX      ((duk_int16_t) 0x7fff)
7307 
7308 struct duk_hnatfunc {
7309 	/* shared object part */
7310 	duk_hobject obj;
7311 
7312 	duk_c_function func;
7313 	duk_int16_t nargs;
7314 	duk_int16_t magic;
7315 
7316 	/* The 'magic' field allows an opaque 16-bit field to be accessed by the
7317 	 * Duktape/C function.  This allows, for instance, the same native function
7318 	 * to be used for a set of very similar functions, with the 'magic' field
7319 	 * providing the necessary non-argument flags / values to guide the behavior
7320 	 * of the native function.  The value is signed on purpose: it is easier to
7321 	 * convert a signed value to unsigned (simply AND with 0xffff) than vice
7322 	 * versa.
7323 	 *
7324 	 * Note: cannot place nargs/magic into the heaphdr flags, because
7325 	 * duk_hobject takes almost all flags already.
7326 	 */
7327 };
7328 
7329 #endif  /* DUK_HNATFUNC_H_INCLUDED */
7330 /* #include duk_hboundfunc.h */
7331 #line 1 "duk_hboundfunc.h"
7332 /*
7333  *  Bound function representation.
7334  */
7335 
7336 #if !defined(DUK_HBOUNDFUNC_H_INCLUDED)
7337 #define DUK_HBOUNDFUNC_H_INCLUDED
7338 
7339 /* Artificial limit for args length.  Ensures arithmetic won't overflow
7340  * 32 bits when combining bound functions.
7341  */
7342 #define DUK_HBOUNDFUNC_MAX_ARGS 0x20000000UL
7343 
7344 #define DUK_ASSERT_HBOUNDFUNC_VALID(h) do { \
7345 		DUK_ASSERT((h) != NULL); \
7346 		DUK_ASSERT(DUK_HOBJECT_IS_BOUNDFUNC((duk_hobject *) (h))); \
7347 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&(h)->target) || \
7348 		           (DUK_TVAL_IS_OBJECT(&(h)->target) && \
7349 		            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&(h)->target)))); \
7350 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&(h)->this_binding)); \
7351 		DUK_ASSERT((h)->nargs == 0 || (h)->args != NULL); \
7352 	} while (0)
7353 
7354 struct duk_hboundfunc {
7355 	/* Shared object part. */
7356 	duk_hobject obj;
7357 
7358 	/* Final target function, stored as duk_tval so that lightfunc can be
7359 	 * represented too.
7360 	 */
7361 	duk_tval target;
7362 
7363 	/* This binding. */
7364 	duk_tval this_binding;
7365 
7366 	/* Arguments to prepend. */
7367 	duk_tval *args;  /* Separate allocation. */
7368 	duk_idx_t nargs;
7369 };
7370 
7371 #endif  /* DUK_HBOUNDFUNC_H_INCLUDED */
7372 /* #include duk_hbufobj.h */
7373 #line 1 "duk_hbufobj.h"
7374 /*
7375  *  Heap Buffer object representation.  Used for all Buffer variants.
7376  */
7377 
7378 #if !defined(DUK_HBUFOBJ_H_INCLUDED)
7379 #define DUK_HBUFOBJ_H_INCLUDED
7380 
7381 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
7382 
7383 /* All element accessors are host endian now (driven by TypedArray spec). */
7384 #define DUK_HBUFOBJ_ELEM_UINT8           0
7385 #define DUK_HBUFOBJ_ELEM_UINT8CLAMPED    1
7386 #define DUK_HBUFOBJ_ELEM_INT8            2
7387 #define DUK_HBUFOBJ_ELEM_UINT16          3
7388 #define DUK_HBUFOBJ_ELEM_INT16           4
7389 #define DUK_HBUFOBJ_ELEM_UINT32          5
7390 #define DUK_HBUFOBJ_ELEM_INT32           6
7391 #define DUK_HBUFOBJ_ELEM_FLOAT32         7
7392 #define DUK_HBUFOBJ_ELEM_FLOAT64         8
7393 #define DUK_HBUFOBJ_ELEM_MAX             8
7394 
7395 #define DUK_ASSERT_HBUFOBJ_VALID(h) do { \
7396 		DUK_ASSERT((h) != NULL); \
7397 		DUK_ASSERT((h)->shift <= 3); \
7398 		DUK_ASSERT((h)->elem_type <= DUK_HBUFOBJ_ELEM_MAX); \
7399 		DUK_ASSERT(((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8) || \
7400 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT8CLAMPED) || \
7401 		           ((h)->shift == 0 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT8) || \
7402 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT16) || \
7403 		           ((h)->shift == 1 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT16) || \
7404 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_UINT32) || \
7405 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_INT32) || \
7406 		           ((h)->shift == 2 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT32) || \
7407 		           ((h)->shift == 3 && (h)->elem_type == DUK_HBUFOBJ_ELEM_FLOAT64)); \
7408 		DUK_ASSERT((h)->is_typedarray == 0 || (h)->is_typedarray == 1); \
7409 		DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) (h))); \
7410 		if ((h)->buf == NULL) { \
7411 			DUK_ASSERT((h)->offset == 0); \
7412 			DUK_ASSERT((h)->length == 0); \
7413 		} else { \
7414 			/* No assertions for offset or length; in particular, \
7415 			 * it's OK for length to be longer than underlying \
7416 			 * buffer.  Just ensure they don't wrap when added. \
7417 			 */ \
7418 			DUK_ASSERT((h)->offset + (h)->length >= (h)->offset); \
7419 		} \
7420 	} while (0)
7421 
7422 /* Get the current data pointer (caller must ensure buf != NULL) as a
7423  * duk_uint8_t ptr.  Note that the result may be NULL if the underlying
7424  * buffer has zero size and is not a fixed buffer.
7425  */
7426 #define DUK_HBUFOBJ_GET_SLICE_BASE(heap,h) \
7427 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7428 	(((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR((heap), (h)->buf)) + (h)->offset))
7429 
7430 /* True if slice is full, i.e. offset is zero and length covers the entire
7431  * buffer.  This status may change independently of the duk_hbufobj if
7432  * the underlying buffer is dynamic and changes without the hbufobj
7433  * being changed.
7434  */
7435 #define DUK_HBUFOBJ_FULL_SLICE(h) \
7436 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7437 	((h)->offset == 0 && (h)->length == DUK_HBUFFER_GET_SIZE((h)->buf)))
7438 
7439 /* Validate that the whole slice [0,length[ is contained in the underlying
7440  * buffer.  Caller must ensure 'buf' != NULL.
7441  */
7442 #define DUK_HBUFOBJ_VALID_SLICE(h) \
7443 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7444 	((h)->offset + (h)->length <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7445 
7446 /* Validate byte read/write for virtual 'offset', i.e. check that the
7447  * offset, taking into account h->offset, is within the underlying
7448  * buffer size.  This is a safety check which is needed to ensure
7449  * that even a misconfigured duk_hbufobj never causes memory unsafe
7450  * behavior (e.g. if an underlying dynamic buffer changes after being
7451  * setup).  Caller must ensure 'buf' != NULL.
7452  */
7453 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_INCL(h,off) \
7454 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7455 	((h)->offset + (off) < DUK_HBUFFER_GET_SIZE((h)->buf)))
7456 
7457 #define DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h,off) \
7458 	(DUK_ASSERT_EXPR((h) != NULL), DUK_ASSERT_EXPR((h)->buf != NULL), \
7459 	((h)->offset + (off) <= DUK_HBUFFER_GET_SIZE((h)->buf)))
7460 
7461 /* Clamp an input byte length (already assumed to be within the nominal
7462  * duk_hbufobj 'length') to the current dynamic buffer limits to yield
7463  * a byte length limit that's safe for memory accesses.  This value can
7464  * be invalidated by any side effect because it may trigger a user
7465  * callback that resizes the underlying buffer.
7466  */
7467 #define DUK_HBUFOBJ_CLAMP_BYTELENGTH(h,len) \
7468 	(DUK_ASSERT_EXPR((h) != NULL), \
7469 	duk_hbufobj_clamp_bytelength((h), (len)))
7470 
7471 /* Typed arrays have virtual indices, ArrayBuffer and DataView do not. */
7472 #define DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h)  ((h)->is_typedarray)
7473 
7474 struct duk_hbufobj {
7475 	/* Shared object part. */
7476 	duk_hobject obj;
7477 
7478 	/* Underlying buffer (refcounted), may be NULL. */
7479 	duk_hbuffer *buf;
7480 
7481 	/* .buffer reference to an ArrayBuffer, may be NULL. */
7482 	duk_hobject *buf_prop;
7483 
7484 	/* Slice and accessor information.
7485 	 *
7486 	 * Because the underlying buffer may be dynamic, these may be
7487 	 * invalidated by the buffer being modified so that both offset
7488 	 * and length should be validated before every access.  Behavior
7489 	 * when the underlying buffer has changed doesn't need to be clean:
7490 	 * virtual 'length' doesn't need to be affected, reads can return
7491 	 * zero/NaN, and writes can be ignored.
7492 	 *
7493 	 * Note that a data pointer cannot be precomputed because 'buf' may
7494 	 * be dynamic and its pointer unstable.
7495 	 */
7496 
7497 	duk_uint_t offset;       /* byte offset to buf */
7498 	duk_uint_t length;       /* byte index limit for element access, exclusive */
7499 	duk_uint8_t shift;       /* element size shift:
7500 	                          *   0 = u8/i8
7501 	                          *   1 = u16/i16
7502 	                          *   2 = u32/i32/float
7503 	                          *   3 = double
7504 	                          */
7505 	duk_uint8_t elem_type;   /* element type */
7506 	duk_uint8_t is_typedarray;
7507 };
7508 
7509 DUK_INTERNAL_DECL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len);
7510 DUK_INTERNAL_DECL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf);
7511 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);
7512 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);
7513 DUK_INTERNAL_DECL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx);
7514 
7515 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
7516 #endif  /* DUK_HBUFOBJ_H_INCLUDED */
7517 /* #include duk_hthread.h */
7518 #line 1 "duk_hthread.h"
7519 /*
7520  *  Heap thread object representation.
7521  *
7522  *  duk_hthread is also the 'context' for public API functions via a
7523  *  different typedef.  Most API calls operate on the topmost frame
7524  *  of the value stack only.
7525  */
7526 
7527 #if !defined(DUK_HTHREAD_H_INCLUDED)
7528 #define DUK_HTHREAD_H_INCLUDED
7529 
7530 /*
7531  *  Stack constants
7532  */
7533 
7534 /* Initial valstack size, roughly 0.7kiB. */
7535 #define DUK_VALSTACK_INITIAL_SIZE       96U
7536 
7537 /* Internal extra elements assumed on function entry, always added to
7538  * user-defined 'extra' for e.g. the duk_check_stack() call.
7539  */
7540 #define DUK_VALSTACK_INTERNAL_EXTRA     32U
7541 
7542 /* Number of elements guaranteed to be user accessible (in addition to call
7543  * arguments) on Duktape/C function entry.  This is the major public API
7544  * commitment.
7545  */
7546 #define DUK_VALSTACK_API_ENTRY_MINIMUM  DUK_API_ENTRY_STACK
7547 
7548 /*
7549  *  Activation defines
7550  */
7551 
7552 #define DUK_ACT_FLAG_STRICT             (1U << 0)  /* function executes in strict mode */
7553 #define DUK_ACT_FLAG_TAILCALLED         (1U << 1)  /* activation has tail called one or more times */
7554 #define DUK_ACT_FLAG_CONSTRUCT          (1U << 2)  /* function executes as a constructor (called via "new") */
7555 #define DUK_ACT_FLAG_PREVENT_YIELD      (1U << 3)  /* activation prevents yield (native call or "new") */
7556 #define DUK_ACT_FLAG_DIRECT_EVAL        (1U << 4)  /* activation is a direct eval call */
7557 #define DUK_ACT_FLAG_CONSTRUCT_PROXY    (1U << 5)  /* activation is for Proxy 'construct' call, special return value handling */
7558 #define DUK_ACT_FLAG_BREAKPOINT_ACTIVE  (1U << 6)  /* activation has active breakpoint(s) */
7559 
7560 #define DUK_ACT_GET_FUNC(act)           ((act)->func)
7561 
7562 /*
7563  *  Flags for __FILE__ / __LINE__ registered into tracedata
7564  */
7565 
7566 #define DUK_TB_FLAG_NOBLAME_FILELINE    (1U << 0)  /* don't report __FILE__ / __LINE__ as fileName/lineNumber */
7567 
7568 /*
7569  *  Catcher defines
7570  */
7571 
7572 /* XXX: remove catcher type entirely */
7573 
7574 /* flags field: LLLLLLFT, L = label (24 bits), F = flags (4 bits), T = type (4 bits) */
7575 #define DUK_CAT_TYPE_MASK            0x0000000fUL
7576 #define DUK_CAT_TYPE_BITS            4
7577 #define DUK_CAT_LABEL_MASK           0xffffff00UL
7578 #define DUK_CAT_LABEL_BITS           24
7579 #define DUK_CAT_LABEL_SHIFT          8
7580 
7581 #define DUK_CAT_FLAG_CATCH_ENABLED          (1U << 4)   /* catch part will catch */
7582 #define DUK_CAT_FLAG_FINALLY_ENABLED        (1U << 5)   /* finally part will catch */
7583 #define DUK_CAT_FLAG_CATCH_BINDING_ENABLED  (1U << 6)   /* request to create catch binding */
7584 #define DUK_CAT_FLAG_LEXENV_ACTIVE          (1U << 7)   /* catch or with binding is currently active */
7585 
7586 #define DUK_CAT_TYPE_UNKNOWN         0
7587 #define DUK_CAT_TYPE_TCF             1
7588 #define DUK_CAT_TYPE_LABEL           2
7589 
7590 #define DUK_CAT_GET_TYPE(c)          ((c)->flags & DUK_CAT_TYPE_MASK)
7591 #define DUK_CAT_GET_LABEL(c)         (((c)->flags & DUK_CAT_LABEL_MASK) >> DUK_CAT_LABEL_SHIFT)
7592 
7593 #define DUK_CAT_HAS_CATCH_ENABLED(c)           ((c)->flags & DUK_CAT_FLAG_CATCH_ENABLED)
7594 #define DUK_CAT_HAS_FINALLY_ENABLED(c)         ((c)->flags & DUK_CAT_FLAG_FINALLY_ENABLED)
7595 #define DUK_CAT_HAS_CATCH_BINDING_ENABLED(c)   ((c)->flags & DUK_CAT_FLAG_CATCH_BINDING_ENABLED)
7596 #define DUK_CAT_HAS_LEXENV_ACTIVE(c)           ((c)->flags & DUK_CAT_FLAG_LEXENV_ACTIVE)
7597 
7598 #define DUK_CAT_SET_CATCH_ENABLED(c)    do { \
7599 		(c)->flags |= DUK_CAT_FLAG_CATCH_ENABLED; \
7600 	} while (0)
7601 #define DUK_CAT_SET_FINALLY_ENABLED(c)  do { \
7602 		(c)->flags |= DUK_CAT_FLAG_FINALLY_ENABLED; \
7603 	} while (0)
7604 #define DUK_CAT_SET_CATCH_BINDING_ENABLED(c)    do { \
7605 		(c)->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7606 	} while (0)
7607 #define DUK_CAT_SET_LEXENV_ACTIVE(c)    do { \
7608 		(c)->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE; \
7609 	} while (0)
7610 
7611 #define DUK_CAT_CLEAR_CATCH_ENABLED(c)    do { \
7612 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_ENABLED; \
7613 	} while (0)
7614 #define DUK_CAT_CLEAR_FINALLY_ENABLED(c)  do { \
7615 		(c)->flags &= ~DUK_CAT_FLAG_FINALLY_ENABLED; \
7616 	} while (0)
7617 #define DUK_CAT_CLEAR_CATCH_BINDING_ENABLED(c)    do { \
7618 		(c)->flags &= ~DUK_CAT_FLAG_CATCH_BINDING_ENABLED; \
7619 	} while (0)
7620 #define DUK_CAT_CLEAR_LEXENV_ACTIVE(c)    do { \
7621 		(c)->flags &= ~DUK_CAT_FLAG_LEXENV_ACTIVE; \
7622 	} while (0)
7623 
7624 /*
7625  *  Thread defines
7626  */
7627 
7628 #if defined(DUK_USE_ROM_STRINGS)
7629 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7630 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
7631 #else  /* DUK_USE_ROM_STRINGS */
7632 #if defined(DUK_USE_HEAPPTR16)
7633 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7634 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((thr)->heap->heap_udata, (thr)->strs16[(idx)]))
7635 #else
7636 #define DUK_HTHREAD_GET_STRING(thr,idx) \
7637 	((thr)->strs[(idx)])
7638 #endif
7639 #endif  /* DUK_USE_ROM_STRINGS */
7640 
7641 /* values for the state field */
7642 #define DUK_HTHREAD_STATE_INACTIVE     1   /* thread not currently running */
7643 #define DUK_HTHREAD_STATE_RUNNING      2   /* thread currently running (only one at a time) */
7644 #define DUK_HTHREAD_STATE_RESUMED      3   /* thread resumed another thread (active but not running) */
7645 #define DUK_HTHREAD_STATE_YIELDED      4   /* thread has yielded */
7646 #define DUK_HTHREAD_STATE_TERMINATED   5   /* thread has terminated */
7647 
7648 /* Executor interrupt default interval when nothing else requires a
7649  * smaller value.  The default interval must be small enough to allow
7650  * for reasonable execution timeout checking but large enough to keep
7651  * impact on execution performance low.
7652  */
7653 #if defined(DUK_USE_INTERRUPT_COUNTER)
7654 #define DUK_HTHREAD_INTCTR_DEFAULT     (256L * 1024L)
7655 #endif
7656 
7657 /*
7658  *  Assert context is valid: non-NULL pointer, fields look sane.
7659  *
7660  *  This is used by public API call entrypoints to catch invalid 'ctx' pointers
7661  *  as early as possible; invalid 'ctx' pointers cause very odd and difficult to
7662  *  diagnose behavior so it's worth checking even when the check is not 100%.
7663  */
7664 
7665 /* Assertions for internals. */
7666 #define DUK_ASSERT_HTHREAD_VALID(thr) do { \
7667 		DUK_ASSERT((thr) != NULL); \
7668 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) (thr)) == DUK_HTYPE_OBJECT); \
7669 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD((duk_hobject *) (thr))); \
7670 		DUK_ASSERT((thr)->unused1 == 0); \
7671 		DUK_ASSERT((thr)->unused2 == 0); \
7672 	} while (0)
7673 
7674 /* Assertions for public API calls; a bit stronger. */
7675 #define DUK_ASSERT_CTX_VALID(thr) do { \
7676 		DUK_ASSERT((thr) != NULL); \
7677 		DUK_ASSERT_HTHREAD_VALID((thr)); \
7678 		DUK_ASSERT((thr)->valstack != NULL); \
7679 		DUK_ASSERT((thr)->valstack_bottom != NULL); \
7680 		DUK_ASSERT((thr)->valstack_top != NULL); \
7681 		DUK_ASSERT((thr)->valstack_end != NULL); \
7682 		DUK_ASSERT((thr)->valstack_alloc_end != NULL); \
7683 		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack); \
7684 		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack); \
7685 		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack); \
7686 		DUK_ASSERT((thr)->valstack_top >= (thr)->valstack_bottom); \
7687 		DUK_ASSERT((thr)->valstack_end >= (thr)->valstack_top); \
7688 		DUK_ASSERT((thr)->valstack_alloc_end >= (thr)->valstack_end); \
7689 	} while (0)
7690 
7691 /* Assertions for API call entry specifically.  Checks 'ctx' but also may
7692  * check internal state (e.g. not in a debugger transport callback).
7693  */
7694 #define DUK_ASSERT_API_ENTRY(thr) do { \
7695 		DUK_ASSERT_CTX_VALID((thr)); \
7696 		DUK_ASSERT((thr)->heap != NULL); \
7697 		DUK_ASSERT((thr)->heap->dbg_calling_transport == 0); \
7698 	} while (0)
7699 
7700 /*
7701  *  Assertion helpers.
7702  */
7703 
7704 #define DUK_ASSERT_STRIDX_VALID(val) \
7705 	DUK_ASSERT((duk_uint_t) (val) < DUK_HEAP_NUM_STRINGS)
7706 
7707 #define DUK_ASSERT_BIDX_VALID(val) \
7708 	DUK_ASSERT((duk_uint_t) (val) < DUK_NUM_BUILTINS)
7709 
7710 /*
7711  *  Misc
7712  */
7713 
7714 /* Fast access to 'this' binding.  Assumes there's a call in progress. */
7715 #define DUK_HTHREAD_THIS_PTR(thr) \
7716 	(DUK_ASSERT_EXPR((thr) != NULL), \
7717 	 DUK_ASSERT_EXPR((thr)->valstack_bottom > (thr)->valstack), \
7718 	 (thr)->valstack_bottom - 1)
7719 
7720 /*
7721  *  Struct defines
7722  */
7723 
7724 /* Fields are ordered for alignment/packing. */
7725 struct duk_activation {
7726 	duk_tval tv_func;       /* borrowed: full duk_tval for function being executed; for lightfuncs */
7727 	duk_hobject *func;      /* borrowed: function being executed; for bound function calls, this is the final, real function, NULL for lightfuncs */
7728 	duk_activation *parent; /* previous (parent) activation (or NULL if none) */
7729 	duk_hobject *var_env;   /* current variable environment (may be NULL if delayed) */
7730 	duk_hobject *lex_env;   /* current lexical environment (may be NULL if delayed) */
7731 	duk_catcher *cat;       /* current catcher (or NULL) */
7732 
7733 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
7734 	/* Previous value of 'func' caller, restored when unwound.  Only in use
7735 	 * when 'func' is non-strict.
7736 	 */
7737 	duk_hobject *prev_caller;
7738 #endif
7739 
7740 	duk_instr_t *curr_pc;   /* next instruction to execute (points to 'func' bytecode, stable pointer), NULL for native calls */
7741 
7742 	/* bottom_byteoff and retval_byteoff are only used for book-keeping
7743 	 * of ECMAScript-initiated calls, to allow returning to an ECMAScript
7744 	 * function properly.
7745 	 */
7746 
7747 	/* Bottom of valstack for this activation, used to reset
7748 	 * valstack_bottom on return; offset is absolute.  There's
7749 	 * no need to track 'top' because native call handling deals
7750 	 * with that using locals, and for ECMAScript returns 'nregs'
7751 	 * indicates the necessary top.
7752 	 */
7753 	duk_size_t bottom_byteoff;
7754 
7755 	/* Return value when returning to this activation (points to caller
7756 	 * reg, not callee reg); offset is absolute (only set if activation is
7757 	 * not topmost).
7758 	 *
7759 	 * Note: bottom_byteoff is always set, while retval_byteoff is only
7760 	 * applicable for activations below the topmost one.  Currently
7761 	 * retval_byteoff for the topmost activation is considered garbage
7762 	 * (and it not initialized on entry or cleared on return; may contain
7763 	 * previous or garbage values).
7764 	 */
7765 	duk_size_t retval_byteoff;
7766 
7767 	/* Current 'this' binding is the value just below bottom.
7768 	 * Previously, 'this' binding was handled with an index to the
7769 	 * (calling) valstack.  This works for everything except tail
7770 	 * calls, which must not "accumulate" valstack temps.
7771 	 */
7772 
7773 	/* Value stack reserve (valstack_end) byte offset to be restored
7774 	 * when returning to this activation.  Only used by the bytecode
7775 	 * executor.
7776 	 */
7777 	duk_size_t reserve_byteoff;
7778 
7779 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7780 	duk_uint32_t prev_line; /* needed for stepping */
7781 #endif
7782 
7783 	duk_small_uint_t flags;
7784 };
7785 
7786 struct duk_catcher {
7787 	duk_catcher *parent;            /* previous (parent) catcher (or NULL if none) */
7788 	duk_hstring *h_varname;         /* borrowed reference to catch variable name (or NULL if none) */
7789 	                                /* (reference is valid as long activation exists) */
7790 	duk_instr_t *pc_base;           /* resume execution from pc_base or pc_base+1 (points to 'func' bytecode, stable pointer) */
7791 	duk_size_t idx_base;            /* idx_base and idx_base+1 get completion value and type */
7792 	duk_uint32_t flags;             /* type and control flags, label number */
7793 	/* XXX: could pack 'flags' and 'idx_base' to same value in practice,
7794 	 * on 32-bit targets this would make duk_catcher 16 bytes.
7795 	 */
7796 };
7797 
7798 struct duk_hthread {
7799 	/* Shared object part */
7800 	duk_hobject obj;
7801 
7802 	/* Pointer to bytecode executor's 'curr_pc' variable.  Used to copy
7803 	 * the current PC back into the topmost activation when activation
7804 	 * state is about to change (or "syncing" is otherwise needed).  This
7805 	 * is rather awkward but important for performance, see execution.rst.
7806 	 */
7807 	duk_instr_t **ptr_curr_pc;
7808 
7809 	/* Backpointers. */
7810 	duk_heap *heap;
7811 
7812 	/* Current strictness flag: affects API calls. */
7813 	duk_uint8_t strict;
7814 
7815 	/* Thread state. */
7816 	duk_uint8_t state;
7817 	duk_uint8_t unused1;
7818 	duk_uint8_t unused2;
7819 
7820 	/* XXX: Valstack and callstack are currently assumed to have non-NULL
7821 	 * pointers.  Relaxing this would not lead to big benefits (except
7822 	 * perhaps for terminated threads).
7823 	 */
7824 
7825 	/* Value stack: these are expressed as pointers for faster stack
7826 	 * manipulation.  [valstack,valstack_top[ is GC-reachable,
7827 	 * [valstack_top,valstack_alloc_end[ is not GC-reachable but kept
7828 	 * initialized as 'undefined'.  [valstack,valstack_end[ is the
7829 	 * guaranteed/reserved space and the valstack cannot be resized to
7830 	 * a smaller size.  [valstack_end,valstack_alloc_end[ is currently
7831 	 * allocated slack that can be used to grow the current guaranteed
7832 	 * space but may be shrunk away without notice.
7833 	 *
7834 	 *
7835 	 * <----------------------- guaranteed --->
7836 	 *                                        <---- slack --->
7837 	 *               <--- frame --->
7838 	 * .-------------+=============+----------+--------------.
7839 	 * |xxxxxxxxxxxxx|yyyyyyyyyyyyy|uuuuuuuuuu|uuuuuuuuuuuuuu|
7840 	 * `-------------+=============+----------+--------------'
7841 	 *
7842 	 * ^             ^             ^          ^              ^
7843 	 * |             |             |          |              |
7844 	 * valstack      bottom        top        end            alloc_end
7845 	 *
7846 	 *     xxx = arbitrary values, below current frame
7847 	 *     yyy = arbitrary values, inside current frame
7848 	 *     uuu = outside active value stack, initialized to 'undefined'
7849 	 */
7850 	duk_tval *valstack;                     /* start of valstack allocation */
7851 	duk_tval *valstack_end;                 /* end of valstack reservation/guarantee (exclusive) */
7852 	duk_tval *valstack_alloc_end;           /* end of valstack allocation */
7853 	duk_tval *valstack_bottom;              /* bottom of current frame */
7854 	duk_tval *valstack_top;                 /* top of current frame (exclusive) */
7855 
7856 	/* Call stack, represented as a linked list starting from the current
7857 	 * activation (or NULL if nothing is active).
7858 	 */
7859 	duk_activation *callstack_curr;         /* current activation (or NULL if none) */
7860 	duk_size_t callstack_top;               /* number of activation records in callstack (0 if none) */
7861 	duk_size_t callstack_preventcount;      /* number of activation records in callstack preventing a yield */
7862 
7863 	/* Yield/resume book-keeping. */
7864 	duk_hthread *resumer;                   /* who resumed us (if any) */
7865 
7866 	/* Current compiler state (if any), used for augmenting SyntaxErrors. */
7867 	duk_compiler_ctx *compile_ctx;
7868 
7869 #if defined(DUK_USE_INTERRUPT_COUNTER)
7870 	/* Interrupt counter for triggering a slow path check for execution
7871 	 * timeout, debugger interaction such as breakpoints, etc.  The value
7872 	 * is valid for the current running thread, and both the init and
7873 	 * counter values are copied whenever a thread switch occurs.  It's
7874 	 * important for the counter to be conveniently accessible for the
7875 	 * bytecode executor inner loop for performance reasons.
7876 	 */
7877 	duk_int_t interrupt_counter;    /* countdown state */
7878 	duk_int_t interrupt_init;       /* start value for current countdown */
7879 #endif
7880 
7881 	/* Builtin-objects; may or may not be shared with other threads,
7882 	 * threads existing in different "compartments" will have different
7883 	 * built-ins.  Must be stored on a per-thread basis because there
7884 	 * is no intermediate structure for a thread group / compartment.
7885 	 * This takes quite a lot of space, currently 43x4 = 172 bytes on
7886 	 * 32-bit platforms.
7887 	 *
7888 	 * In some cases the builtins array could be ROM based, but it's
7889 	 * sometimes edited (e.g. for sandboxing) so it's better to keep
7890 	 * this array in RAM.
7891 	 */
7892 	duk_hobject *builtins[DUK_NUM_BUILTINS];
7893 
7894 	/* Convenience copies from heap/vm for faster access. */
7895 #if defined(DUK_USE_ROM_STRINGS)
7896 	/* No field needed when strings are in ROM. */
7897 #else
7898 #if defined(DUK_USE_HEAPPTR16)
7899 	duk_uint16_t *strs16;
7900 #else
7901 	duk_hstring **strs;
7902 #endif
7903 #endif
7904 };
7905 
7906 /*
7907  *  Prototypes
7908  */
7909 
7910 DUK_INTERNAL_DECL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to);
7911 DUK_INTERNAL_DECL void duk_hthread_create_builtin_objects(duk_hthread *thr);
7912 DUK_INTERNAL_DECL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr);
7913 DUK_INTERNAL_DECL void duk_hthread_terminate(duk_hthread *thr);
7914 
7915 DUK_INTERNAL_DECL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr);
7916 DUK_INTERNAL_DECL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act);
7917 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_norz(duk_hthread *thr);
7918 DUK_INTERNAL_DECL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr);
7919 DUK_INTERNAL_DECL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level);
7920 
7921 DUK_INTERNAL_DECL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr);
7922 DUK_INTERNAL_DECL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat);
7923 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act);
7924 DUK_INTERNAL_DECL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act);
7925 
7926 #if defined(DUK_USE_FINALIZER_TORTURE)
7927 DUK_INTERNAL_DECL void duk_hthread_valstack_torture_realloc(duk_hthread *thr);
7928 #endif
7929 
7930 DUK_INTERNAL_DECL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
7931 
7932 #if defined(DUK_USE_DEBUGGER_SUPPORT)
7933 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act);
7934 #endif
7935 DUK_INTERNAL_DECL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act);
7936 DUK_INTERNAL_DECL void duk_hthread_sync_currpc(duk_hthread *thr);
7937 DUK_INTERNAL_DECL void duk_hthread_sync_and_null_currpc(duk_hthread *thr);
7938 
7939 #endif  /* DUK_HTHREAD_H_INCLUDED */
7940 /* #include duk_harray.h */
7941 #line 1 "duk_harray.h"
7942 /*
7943  *  Array object representation, used for actual Array instances.
7944  *
7945  *  All objects with the exotic array behavior (which must coincide with having
7946  *  internal class array) MUST be duk_harrays.  No other object can be a
7947  *  duk_harray.  However, duk_harrays may not always have an array part.
7948  */
7949 
7950 #if !defined(DUK_HARRAY_H_INCLUDED)
7951 #define DUK_HARRAY_H_INCLUDED
7952 
7953 #define DUK_ASSERT_HARRAY_VALID(h) do { \
7954 		DUK_ASSERT((h) != NULL); \
7955 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) (h))); \
7956 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY((duk_hobject *) (h))); \
7957 	} while (0)
7958 
7959 #define DUK_HARRAY_LENGTH_WRITABLE(h)         (!(h)->length_nonwritable)
7960 #define DUK_HARRAY_LENGTH_NONWRITABLE(h)      ((h)->length_nonwritable)
7961 #define DUK_HARRAY_SET_LENGTH_WRITABLE(h)     do { (h)->length_nonwritable = 0; } while (0)
7962 #define DUK_HARRAY_SET_LENGTH_NONWRITABLE(h)  do { (h)->length_nonwritable = 1; } while (0)
7963 
7964 struct duk_harray {
7965 	/* Shared object part. */
7966 	duk_hobject obj;
7967 
7968 	/* Array .length.
7969 	 *
7970 	 * At present Array .length may be smaller, equal, or even larger
7971 	 * than the allocated underlying array part.  Fast path code must
7972 	 * always take this into account carefully.
7973 	 */
7974 	duk_uint32_t length;
7975 
7976 	/* Array .length property attributes.  The property is always
7977 	 * non-enumerable and non-configurable.  It's initially writable
7978 	 * but per Object.defineProperty() rules it can be made non-writable
7979 	 * even if it is non-configurable.  Thus we need to track the
7980 	 * writability explicitly.
7981 	 *
7982 	 * XXX: this field to be eliminated and moved into duk_hobject
7983 	 * flags field to save space.
7984 	 */
7985 	duk_bool_t length_nonwritable;
7986 };
7987 
7988 #endif  /* DUK_HARRAY_H_INCLUDED */
7989 /* #include duk_henv.h */
7990 #line 1 "duk_henv.h"
7991 /*
7992  *  Environment object representation.
7993  */
7994 
7995 #if !defined(DUK_HENV_H_INCLUDED)
7996 #define DUK_HENV_H_INCLUDED
7997 
7998 #define DUK_ASSERT_HDECENV_VALID(h) do { \
7999 		DUK_ASSERT((h) != NULL); \
8000 		DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) (h))); \
8001 		DUK_ASSERT((h)->thread == NULL || (h)->varmap != NULL); \
8002 	} while (0)
8003 
8004 #define DUK_ASSERT_HOBJENV_VALID(h) do { \
8005 		DUK_ASSERT((h) != NULL); \
8006 		DUK_ASSERT(DUK_HOBJECT_IS_OBJENV((duk_hobject *) (h))); \
8007 		DUK_ASSERT((h)->target != NULL); \
8008 		DUK_ASSERT((h)->has_this == 0 || (h)->has_this == 1); \
8009 	} while (0)
8010 
8011 struct duk_hdecenv {
8012 	/* Shared object part. */
8013 	duk_hobject obj;
8014 
8015 	/* These control variables provide enough information to access live
8016 	 * variables for a closure that is still open.  If thread == NULL,
8017 	 * the record is closed and the identifiers are in the property table.
8018 	 */
8019 	duk_hthread *thread;
8020 	duk_hobject *varmap;
8021 	duk_size_t regbase_byteoff;
8022 };
8023 
8024 struct duk_hobjenv {
8025 	/* Shared object part. */
8026 	duk_hobject obj;
8027 
8028 	/* Target object and 'this' binding for object binding. */
8029 	duk_hobject *target;
8030 
8031 	/* The 'target' object is used as a this binding in only some object
8032 	 * environments.  For example, the global environment does not provide
8033 	 * a this binding, but a with statement does.
8034 	 */
8035 	duk_bool_t has_this;
8036 };
8037 
8038 #endif  /* DUK_HENV_H_INCLUDED */
8039 /* #include duk_hbuffer.h */
8040 #line 1 "duk_hbuffer.h"
8041 /*
8042  *  Heap buffer representation.
8043  *
8044  *  Heap allocated user data buffer which is either:
8045  *
8046  *    1. A fixed size buffer (data follows header statically)
8047  *    2. A dynamic size buffer (data pointer follows header)
8048  *
8049  *  The data pointer for a variable size buffer of zero size may be NULL.
8050  */
8051 
8052 #if !defined(DUK_HBUFFER_H_INCLUDED)
8053 #define DUK_HBUFFER_H_INCLUDED
8054 
8055 /*
8056  *  Flags
8057  *
8058  *  Fixed buffer:     0
8059  *  Dynamic buffer:   DUK_HBUFFER_FLAG_DYNAMIC
8060  *  External buffer:  DUK_HBUFFER_FLAG_DYNAMIC | DUK_HBUFFER_FLAG_EXTERNAL
8061  */
8062 
8063 #define DUK_HBUFFER_FLAG_DYNAMIC                  DUK_HEAPHDR_USER_FLAG(0)    /* buffer is behind a pointer, dynamic or external */
8064 #define DUK_HBUFFER_FLAG_EXTERNAL                 DUK_HEAPHDR_USER_FLAG(1)    /* buffer pointer is to an externally allocated buffer */
8065 
8066 #define DUK_HBUFFER_HAS_DYNAMIC(x)                DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8067 #define DUK_HBUFFER_HAS_EXTERNAL(x)               DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8068 
8069 #define DUK_HBUFFER_SET_DYNAMIC(x)                DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8070 #define DUK_HBUFFER_SET_EXTERNAL(x)               DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8071 
8072 #define DUK_HBUFFER_CLEAR_DYNAMIC(x)              DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_DYNAMIC)
8073 #define DUK_HBUFFER_CLEAR_EXTERNAL(x)             DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HBUFFER_FLAG_EXTERNAL)
8074 
8075 /*
8076  *  Misc defines
8077  */
8078 
8079 /* Impose a maximum buffer length for now.  Restricted artificially to
8080  * ensure resize computations or adding a heap header length won't
8081  * overflow size_t and that a signed duk_int_t can hold a buffer
8082  * length.  The limit should be synchronized with DUK_HSTRING_MAX_BYTELEN.
8083  */
8084 
8085 #if defined(DUK_USE_BUFLEN16)
8086 #define DUK_HBUFFER_MAX_BYTELEN                   (0x0000ffffUL)
8087 #else
8088 /* Intentionally not 0x7fffffffUL; at least JSON code expects that
8089  * 2*len + 2 fits in 32 bits.
8090  */
8091 #define DUK_HBUFFER_MAX_BYTELEN                   (0x7ffffffeUL)
8092 #endif
8093 
8094 /*
8095  *  Field access
8096  */
8097 
8098 #if defined(DUK_USE_BUFLEN16)
8099 /* size stored in duk_heaphdr unused flag bits */
8100 #define DUK_HBUFFER_GET_SIZE(x)     ((x)->hdr.h_flags >> 16)
8101 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8102 		duk_size_t duk__v; \
8103 		duk__v = (v); \
8104 		DUK_ASSERT(duk__v <= 0xffffUL); \
8105 		(x)->hdr.h_flags = ((x)->hdr.h_flags & 0x0000ffffUL) | (((duk_uint32_t) duk__v) << 16); \
8106 	} while (0)
8107 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8108 		(x)->hdr.h_flags += ((dv) << 16); \
8109 	} while (0)
8110 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8111 		(x)->hdr.h_flags -= ((dv) << 16); \
8112 	} while (0)
8113 #else
8114 #define DUK_HBUFFER_GET_SIZE(x)     (((duk_hbuffer *) (x))->size)
8115 #define DUK_HBUFFER_SET_SIZE(x,v)   do { \
8116 		((duk_hbuffer *) (x))->size = (v); \
8117 	} while (0)
8118 #define DUK_HBUFFER_ADD_SIZE(x,dv)  do { \
8119 		(x)->size += (dv); \
8120 	} while (0)
8121 #define DUK_HBUFFER_SUB_SIZE(x,dv)  do { \
8122 		(x)->size -= (dv); \
8123 	} while (0)
8124 #endif
8125 
8126 #define DUK_HBUFFER_FIXED_GET_SIZE(x)       DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8127 #define DUK_HBUFFER_FIXED_SET_SIZE(x,v)     DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x))
8128 
8129 #define DUK_HBUFFER_DYNAMIC_GET_SIZE(x)     DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8130 #define DUK_HBUFFER_DYNAMIC_SET_SIZE(x,v)   DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8131 #define DUK_HBUFFER_DYNAMIC_ADD_SIZE(x,dv)  DUK_HBUFFER_ADD_SIZE((duk_hbuffer *) (x), (dv))
8132 #define DUK_HBUFFER_DYNAMIC_SUB_SIZE(x,dv)  DUK_HBUFFER_SUB_SIZE((duk_hbuffer *) (x), (dv))
8133 
8134 #define DUK_HBUFFER_EXTERNAL_GET_SIZE(x)    DUK_HBUFFER_GET_SIZE((duk_hbuffer *) (x))
8135 #define DUK_HBUFFER_EXTERNAL_SET_SIZE(x,v)  DUK_HBUFFER_SET_SIZE((duk_hbuffer *) (x), (v))
8136 
8137 #define DUK_HBUFFER_FIXED_GET_DATA_PTR(heap,x)    ((duk_uint8_t *) (((duk_hbuffer_fixed *) (void *) (x)) + 1))
8138 
8139 #if defined(DUK_USE_HEAPPTR16)
8140 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x) \
8141 	((void *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, ((duk_heaphdr *) (x))->h_extra16))
8142 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8143 		((duk_heaphdr *) (x))->h_extra16 = DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (void *) (v)); \
8144 	} while (0)
8145 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8146 		((duk_heaphdr *) (x))->h_extra16 = 0;  /* assume 0 <=> NULL */ \
8147 	} while (0)
8148 #else
8149 #define DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap,x)       ((x)->curr_alloc)
8150 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap,x,v)     do { \
8151 		(x)->curr_alloc = (void *) (v); \
8152 	} while (0)
8153 #define DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(heap,x)  do { \
8154 		(x)->curr_alloc = (void *) NULL; \
8155 	} while (0)
8156 #endif
8157 
8158 /* No pointer compression because pointer is potentially outside of
8159  * Duktape heap.
8160  */
8161 #if defined(DUK_USE_HEAPPTR16)
8162 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8163 	((void *) (x)->curr_alloc)
8164 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8165 		(x)->curr_alloc = (void *) (v); \
8166 	} while (0)
8167 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8168 		(x)->curr_alloc = (void *) NULL; \
8169 	} while (0)
8170 #else
8171 #define DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap,x) \
8172 	((void *) (x)->curr_alloc)
8173 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap,x,v)     do { \
8174 		(x)->curr_alloc = (void *) (v); \
8175 	} while (0)
8176 #define DUK_HBUFFER_EXTERNAL_SET_DATA_PTR_NULL(heap,x)  do { \
8177 		(x)->curr_alloc = (void *) NULL; \
8178 	} while (0)
8179 #endif
8180 
8181 /* Get a pointer to the current buffer contents (matching current allocation
8182  * size).  May be NULL for zero size dynamic/external buffer.
8183  */
8184 #if defined(DUK_USE_HEAPPTR16)
8185 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8186 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8187 		( \
8188 			DUK_HBUFFER_HAS_EXTERNAL((x)) ? \
8189 				DUK_HBUFFER_EXTERNAL_GET_DATA_PTR((heap), (duk_hbuffer_external *) (x)) : \
8190 				DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) \
8191 		) : \
8192 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8193 	)
8194 #else
8195 /* Without heap pointer compression duk_hbuffer_dynamic and duk_hbuffer_external
8196  * have the same layout so checking for fixed vs. dynamic (or external) is enough.
8197  */
8198 #define DUK_HBUFFER_GET_DATA_PTR(heap,x)  ( \
8199 	DUK_HBUFFER_HAS_DYNAMIC((x)) ? \
8200 		DUK_HBUFFER_DYNAMIC_GET_DATA_PTR((heap), (duk_hbuffer_dynamic *) (x)) : \
8201 		DUK_HBUFFER_FIXED_GET_DATA_PTR((heap), (duk_hbuffer_fixed *) (void *) (x)) \
8202 	)
8203 #endif
8204 
8205 /*
8206  *  Structs
8207  */
8208 
8209 /* Shared prefix for all buffer types. */
8210 struct duk_hbuffer {
8211 	duk_heaphdr hdr;
8212 
8213 	/* It's not strictly necessary to track the current size, but
8214 	 * it is useful for writing robust native code.
8215 	 */
8216 
8217 	/* Current size. */
8218 #if defined(DUK_USE_BUFLEN16)
8219 	/* Stored in duk_heaphdr unused flags. */
8220 #else
8221 	duk_size_t size;
8222 #endif
8223 
8224 	/*
8225 	 *  Data following the header depends on the DUK_HBUFFER_FLAG_DYNAMIC
8226 	 *  flag.
8227 	 *
8228 	 *  If the flag is clear (the buffer is a fixed size one), the buffer
8229 	 *  data follows the header directly, consisting of 'size' bytes.
8230 	 *
8231 	 *  If the flag is set, the actual buffer is allocated separately, and
8232 	 *  a few control fields follow the header.  Specifically:
8233 	 *
8234 	 *    - a "void *" pointing to the current allocation
8235 	 *    - a duk_size_t indicating the full allocated size (always >= 'size')
8236 	 *
8237 	 *  If DUK_HBUFFER_FLAG_EXTERNAL is set, the buffer has been allocated
8238 	 *  by user code, so that Duktape won't be able to resize it and won't
8239 	 *  free it.  This allows buffers to point to e.g. an externally
8240 	 *  allocated structure such as a frame buffer.
8241 	 *
8242 	 *  Unlike strings, no terminator byte (NUL) is guaranteed after the
8243 	 *  data.  This would be convenient, but would pad aligned user buffers
8244 	 *  unnecessarily upwards in size.  For instance, if user code requested
8245 	 *  a 64-byte dynamic buffer, 65 bytes would actually be allocated which
8246 	 *  would then potentially round upwards to perhaps 68 or 72 bytes.
8247 	 */
8248 };
8249 
8250 /* Fixed buffer; data follows struct, with proper alignment guaranteed by
8251  * struct size.
8252  */
8253 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8254 #pragma pack(push, 8)
8255 #endif
8256 struct duk_hbuffer_fixed {
8257 	/* A union is used here as a portable struct size / alignment trick:
8258 	 * by adding a 32-bit or a 64-bit (unused) union member, the size of
8259 	 * the struct is effectively forced to be a multiple of 4 or 8 bytes
8260 	 * (respectively) without increasing the size of the struct unless
8261 	 * necessary.
8262 	 */
8263 	union {
8264 		struct {
8265 			duk_heaphdr hdr;
8266 #if defined(DUK_USE_BUFLEN16)
8267 			/* Stored in duk_heaphdr unused flags. */
8268 #else
8269 			duk_size_t size;
8270 #endif
8271 		} s;
8272 #if (DUK_USE_ALIGN_BY == 4)
8273 		duk_uint32_t dummy_for_align4;
8274 #elif (DUK_USE_ALIGN_BY == 8)
8275 		duk_double_t dummy_for_align8_1;
8276 #if defined(DUK_USE_64BIT_OPS)
8277 		duk_uint64_t dummy_for_align8_2;
8278 #endif
8279 #elif (DUK_USE_ALIGN_BY == 1)
8280 		/* no extra padding */
8281 #else
8282 #error invalid DUK_USE_ALIGN_BY
8283 #endif
8284 	} u;
8285 
8286 	/*
8287 	 *  Data follows the struct header.  The struct size is padded by the
8288 	 *  compiler based on the struct members.  This guarantees that the
8289 	 *  buffer data will be aligned-by-4 but not necessarily aligned-by-8.
8290 	 *
8291 	 *  On platforms where alignment does not matter, the struct padding
8292 	 *  could be removed (if there is any).  On platforms where alignment
8293 	 *  by 8 is required, the struct size must be forced to be a multiple
8294 	 *  of 8 by some means.  Without it, some user code may break, and also
8295 	 *  Duktape itself breaks (e.g. the compiler stores duk_tvals in a
8296 	 *  dynamic buffer).
8297 	 */
8298 }
8299 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_GCC_ATTR)
8300 __attribute__ ((aligned (8)))
8301 #elif (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_CLANG_ATTR)
8302 __attribute__ ((aligned (8)))
8303 #endif
8304 ;
8305 #if (DUK_USE_ALIGN_BY == 8) && defined(DUK_USE_PACK_MSVC_PRAGMA)
8306 #pragma pack(pop)
8307 #endif
8308 
8309 /* Dynamic buffer with 'curr_alloc' pointing to a dynamic area allocated using
8310  * heap allocation primitives.  Also used for external buffers when low memory
8311  * options are not used.
8312  */
8313 struct duk_hbuffer_dynamic {
8314 	duk_heaphdr hdr;
8315 
8316 #if defined(DUK_USE_BUFLEN16)
8317 	/* Stored in duk_heaphdr unused flags. */
8318 #else
8319 	duk_size_t size;
8320 #endif
8321 
8322 #if defined(DUK_USE_HEAPPTR16)
8323 	/* Stored in duk_heaphdr h_extra16. */
8324 #else
8325 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8326 #endif
8327 
8328 	/*
8329 	 *  Allocation size for 'curr_alloc' is alloc_size.  There is no
8330 	 *  automatic NUL terminator for buffers (see above for rationale).
8331 	 *
8332 	 *  'curr_alloc' is explicitly allocated with heap allocation
8333 	 *  primitives and will thus always have alignment suitable for
8334 	 *  e.g. duk_tval and an IEEE double.
8335 	 */
8336 };
8337 
8338 /* External buffer with 'curr_alloc' managed by user code and pointing to an
8339  * arbitrary address.  When heap pointer compression is not used, this struct
8340  * has the same layout as duk_hbuffer_dynamic.
8341  */
8342 struct duk_hbuffer_external {
8343 	duk_heaphdr hdr;
8344 
8345 #if defined(DUK_USE_BUFLEN16)
8346 	/* Stored in duk_heaphdr unused flags. */
8347 #else
8348 	duk_size_t size;
8349 #endif
8350 
8351 	/* Cannot be compressed as a heap pointer because may point to
8352 	 * an arbitrary address.
8353 	 */
8354 	void *curr_alloc;  /* may be NULL if alloc_size == 0 */
8355 };
8356 
8357 /*
8358  *  Prototypes
8359  */
8360 
8361 DUK_INTERNAL_DECL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata);
8362 DUK_INTERNAL_DECL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud);  /* indirect allocs */
8363 
8364 /* dynamic buffer ops */
8365 DUK_INTERNAL_DECL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size);
8366 DUK_INTERNAL_DECL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf);
8367 
8368 #endif  /* DUK_HBUFFER_H_INCLUDED */
8369 /* #include duk_hproxy.h */
8370 #line 1 "duk_hproxy.h"
8371 /*
8372  *  Proxy object representation.
8373  */
8374 
8375 #if !defined(DUK_HPROXY_H_INCLUDED)
8376 #define DUK_HPROXY_H_INCLUDED
8377 
8378 #define DUK_ASSERT_HPROXY_VALID(h) do { \
8379 		DUK_ASSERT((h) != NULL); \
8380 		DUK_ASSERT((h)->target != NULL); \
8381 		DUK_ASSERT((h)->handler != NULL); \
8382 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ((duk_hobject *) (h))); \
8383 	} while (0)
8384 
8385 struct duk_hproxy {
8386 	/* Shared object part. */
8387 	duk_hobject obj;
8388 
8389 	/* Proxy target object. */
8390 	duk_hobject *target;
8391 
8392 	/* Proxy handlers (traps). */
8393 	duk_hobject *handler;
8394 };
8395 
8396 #endif  /* DUK_HPROXY_H_INCLUDED */
8397 /* #include duk_heap.h */
8398 #line 1 "duk_heap.h"
8399 /*
8400  *  Heap structure.
8401  *
8402  *  Heap contains allocated heap objects, interned strings, and built-in
8403  *  strings for one or more threads.
8404  */
8405 
8406 #if !defined(DUK_HEAP_H_INCLUDED)
8407 #define DUK_HEAP_H_INCLUDED
8408 
8409 /* alloc function typedefs in duktape.h */
8410 
8411 /*
8412  *  Heap flags
8413  */
8414 
8415 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED            (1U << 0)  /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
8416 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING                        (1U << 1)  /* executor interrupt running (used to avoid nested interrupts) */
8417 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE                       (1U << 2)  /* heap destruction ongoing, finalizer rescue no longer possible */
8418 #define DUK_HEAP_FLAG_DEBUGGER_PAUSED                          (1U << 3)  /* debugger is paused: talk with debug client until step/resume */
8419 
8420 #define DUK__HEAP_HAS_FLAGS(heap,bits)               ((heap)->flags & (bits))
8421 #define DUK__HEAP_SET_FLAGS(heap,bits)  do { \
8422 		(heap)->flags |= (bits); \
8423 	} while (0)
8424 #define DUK__HEAP_CLEAR_FLAGS(heap,bits)  do { \
8425 		(heap)->flags &= ~(bits); \
8426 	} while (0)
8427 
8428 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8429 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap)               DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8430 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap)              DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8431 #define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap)                 DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8432 
8433 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap)   DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8434 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap)               DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8435 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap)              DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8436 #define DUK_HEAP_SET_DEBUGGER_PAUSED(heap)                 DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8437 
8438 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
8439 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap)             DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
8440 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap)            DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
8441 #define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap)               DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
8442 
8443 /*
8444  *  Longjmp types, also double as identifying continuation type for a rethrow (in 'finally')
8445  */
8446 
8447 #define DUK_LJ_TYPE_UNKNOWN      0    /* unused */
8448 #define DUK_LJ_TYPE_THROW        1    /* value1 -> error object */
8449 #define DUK_LJ_TYPE_YIELD        2    /* value1 -> yield value, iserror -> error / normal */
8450 #define DUK_LJ_TYPE_RESUME       3    /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
8451 #define DUK_LJ_TYPE_BREAK        4    /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
8452 #define DUK_LJ_TYPE_CONTINUE     5    /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
8453 #define DUK_LJ_TYPE_RETURN       6    /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
8454 #define DUK_LJ_TYPE_NORMAL       7    /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
8455 
8456 /*
8457  *  Mark-and-sweep flags
8458  *
8459  *  These are separate from heap level flags now but could be merged.
8460  *  The heap structure only contains a 'base mark-and-sweep flags'
8461  *  field and the GC caller can impose further flags.
8462  */
8463 
8464 /* Emergency mark-and-sweep: try extra hard, even at the cost of
8465  * performance.
8466  */
8467 #define DUK_MS_FLAG_EMERGENCY                (1U << 0)
8468 
8469 /* Voluntary mark-and-sweep: triggered periodically. */
8470 #define DUK_MS_FLAG_VOLUNTARY                (1U << 1)
8471 
8472 /* Postpone rescue decisions for reachable objects with FINALIZED set.
8473  * Used during finalize_list processing to avoid incorrect rescue
8474  * decisions due to finalize_list being a reachability root.
8475  */
8476 #define DUK_MS_FLAG_POSTPONE_RESCUE          (1U << 2)
8477 
8478 /* Don't compact objects; needed during object property table resize
8479  * to prevent a recursive resize.  It would suffice to protect only the
8480  * current object being resized, but this is not yet implemented.
8481  */
8482 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION     (1U << 3)
8483 
8484 /*
8485  *  Thread switching
8486  *
8487  *  To switch heap->curr_thread, use the macro below so that interrupt counters
8488  *  get updated correctly.  The macro allows a NULL target thread because that
8489  *  happens e.g. in call handling.
8490  */
8491 
8492 #if defined(DUK_USE_INTERRUPT_COUNTER)
8493 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  duk_heap_switch_thread((heap), (newthr))
8494 #else
8495 #define DUK_HEAP_SWITCH_THREAD(heap,newthr)  do { \
8496 		(heap)->curr_thread = (newthr); \
8497 	} while (0)
8498 #endif
8499 
8500 /*
8501  *  Stats
8502  */
8503 
8504 #if defined(DUK_USE_DEBUG)
8505 #define DUK_STATS_INC(heap,fieldname) do { \
8506 		(heap)->fieldname += 1; \
8507 	} while (0)
8508 #else
8509 #define DUK_STATS_INC(heap,fieldname) do {} while (0)
8510 #endif
8511 
8512 /*
8513  *  Other heap related defines
8514  */
8515 
8516 /* Mark-and-sweep interval is relative to combined count of objects and
8517  * strings kept in the heap during the latest mark-and-sweep pass.
8518  * Fixed point .8 multiplier and .0 adder.  Trigger count (interval) is
8519  * decreased by each (re)allocation attempt (regardless of size), and each
8520  * refzero processed object.
8521  *
8522  * 'SKIP' indicates how many (re)allocations to wait until a retry if
8523  * GC is skipped because there is no thread do it with yet (happens
8524  * only during init phases).
8525  */
8526 #if defined(DUK_USE_REFERENCE_COUNTING)
8527 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              12800L  /* 50x heap size */
8528 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8529 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8530 #else
8531 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT              256L    /* 1x heap size */
8532 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD               1024L
8533 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP              256L
8534 #endif
8535 
8536 /* GC torture. */
8537 #if defined(DUK_USE_GC_TORTURE)
8538 #define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
8539 #else
8540 #define DUK_GC_TORTURE(heap) do { } while (0)
8541 #endif
8542 
8543 /* Stringcache is used for speeding up char-offset-to-byte-offset
8544  * translations for non-ASCII strings.
8545  */
8546 #define DUK_HEAP_STRCACHE_SIZE                            4
8547 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT                16  /* strings up to the this length are not cached */
8548 
8549 /* Some list management macros. */
8550 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr)     duk_heap_insert_into_heap_allocated((heap), (hdr))
8551 #if defined(DUK_USE_REFERENCE_COUNTING)
8552 #define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr)     duk_heap_remove_from_heap_allocated((heap), (hdr))
8553 #endif
8554 #if defined(DUK_USE_FINALIZER_SUPPORT)
8555 #define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr)      duk_heap_insert_into_finalize_list((heap), (hdr))
8556 #define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr)      duk_heap_remove_from_finalize_list((heap), (hdr))
8557 #endif
8558 
8559 /*
8560  *  Built-in strings
8561  */
8562 
8563 /* heap string indices are autogenerated in duk_strings.h */
8564 #if defined(DUK_USE_ROM_STRINGS)
8565 #define DUK_HEAP_GET_STRING(heap,idx) \
8566 	((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)]))
8567 #else  /* DUK_USE_ROM_STRINGS */
8568 #if defined(DUK_USE_HEAPPTR16)
8569 #define DUK_HEAP_GET_STRING(heap,idx) \
8570 	((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)]))
8571 #else
8572 #define DUK_HEAP_GET_STRING(heap,idx) \
8573 	((heap)->strs[(idx)])
8574 #endif
8575 #endif  /* DUK_USE_ROM_STRINGS */
8576 
8577 /*
8578  *  Raw memory calls: relative to heap, but no GC interaction
8579  */
8580 
8581 #define DUK_ALLOC_RAW(heap,size) \
8582 	((heap)->alloc_func((heap)->heap_udata, (size)))
8583 
8584 #define DUK_REALLOC_RAW(heap,ptr,newsize) \
8585 	((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize)))
8586 
8587 #define DUK_FREE_RAW(heap,ptr) \
8588 	((heap)->free_func((heap)->heap_udata, (void *) (ptr)))
8589 
8590 /*
8591  *  Memory calls: relative to heap, GC interaction, but no error throwing.
8592  *
8593  *  XXX: Currently a mark-and-sweep triggered by memory allocation will run
8594  *  using the heap->heap_thread.  This thread is also used for running
8595  *  mark-and-sweep finalization; this is not ideal because it breaks the
8596  *  isolation between multiple global environments.
8597  *
8598  *  Notes:
8599  *
8600  *    - DUK_FREE() is required to ignore NULL and any other possible return
8601  *      value of a zero-sized alloc/realloc (same as ANSI C free()).
8602  *
8603  *    - There is no DUK_REALLOC_ZEROED because we don't assume to know the
8604  *      old size.  Caller must zero the reallocated memory.
8605  *
8606  *    - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered
8607  *      by an allocation failure might invalidate the original 'ptr', thus
8608  *      causing a realloc retry to use an invalid pointer.  Example: we're
8609  *      reallocating the value stack and a finalizer resizes the same value
8610  *      stack during mark-and-sweep.  The indirect variant requests for the
8611  *      current location of the pointer being reallocated using a callback
8612  *      right before every realloc attempt; this circuitous approach is used
8613  *      to avoid strict aliasing issues in a more straightforward indirect
8614  *      pointer (void **) approach.  Note: the pointer in the storage
8615  *      location is read but is NOT updated; the caller must do that.
8616  */
8617 
8618 /* callback for indirect reallocs, request for current pointer */
8619 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud);
8620 
8621 #define DUK_ALLOC(heap,size)                            duk_heap_mem_alloc((heap), (size))
8622 #define DUK_ALLOC_ZEROED(heap,size)                     duk_heap_mem_alloc_zeroed((heap), (size))
8623 #define DUK_REALLOC(heap,ptr,newsize)                   duk_heap_mem_realloc((heap), (ptr), (newsize))
8624 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize)        duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
8625 #define DUK_FREE(heap,ptr)                              duk_heap_mem_free((heap), (ptr))
8626 
8627 /*
8628  *  Checked allocation, relative to a thread
8629  *
8630  *  DUK_FREE_CHECKED() doesn't actually throw, but accepts a 'thr' argument
8631  *  for convenience.
8632  */
8633 
8634 #define DUK_ALLOC_CHECKED(thr,size)                     duk_heap_mem_alloc_checked((thr), (size))
8635 #define DUK_ALLOC_CHECKED_ZEROED(thr,size)              duk_heap_mem_alloc_checked_zeroed((thr), (size))
8636 #define DUK_FREE_CHECKED(thr,ptr)                       duk_heap_mem_free((thr)->heap, (ptr))
8637 
8638 /*
8639  *  Memory constants
8640  */
8641 
8642 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT           10  /* Retry allocation after mark-and-sweep for this
8643                                                               * many times.  A single mark-and-sweep round is
8644                                                               * not guaranteed to free all unreferenced memory
8645                                                               * because of finalization (in fact, ANY number of
8646                                                               * rounds is strictly not enough).
8647                                                               */
8648 
8649 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT  3  /* Starting from this round, use emergency mode
8650                                                               * for mark-and-sweep.
8651                                                               */
8652 
8653 /*
8654  *  Debugger support
8655  */
8656 
8657 /* Maximum number of breakpoints.  Only breakpoints that are set are
8658  * consulted so increasing this has no performance impact.
8659  */
8660 #define DUK_HEAP_MAX_BREAKPOINTS          16
8661 
8662 /* Opcode interval for a Date-based status/peek rate limit check.  Only
8663  * relevant when debugger is attached.  Requesting a timestamp may be a
8664  * slow operation on some platforms so this shouldn't be too low.  On the
8665  * other hand a high value makes Duktape react to a pause request slowly.
8666  */
8667 #define DUK_HEAP_DBG_RATELIMIT_OPCODES    4000
8668 
8669 /* Milliseconds between status notify and transport peeks. */
8670 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS  200
8671 
8672 /* Debugger pause flags. */
8673 #define DUK_PAUSE_FLAG_ONE_OPCODE        (1U << 0)   /* pause when a single opcode has been executed */
8674 #define DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE (1U << 1)   /* one opcode pause actually active; artifact of current implementation */
8675 #define DUK_PAUSE_FLAG_LINE_CHANGE       (1U << 2)   /* pause when current line number changes */
8676 #define DUK_PAUSE_FLAG_FUNC_ENTRY        (1U << 3)   /* pause when entering a function */
8677 #define DUK_PAUSE_FLAG_FUNC_EXIT         (1U << 4)   /* pause when exiting current function */
8678 #define DUK_PAUSE_FLAG_CAUGHT_ERROR      (1U << 5)   /* pause when about to throw an error that is caught */
8679 #define DUK_PAUSE_FLAG_UNCAUGHT_ERROR    (1U << 6)   /* pause when about to throw an error that won't be caught */
8680 
8681 struct duk_breakpoint {
8682 	duk_hstring *filename;
8683 	duk_uint32_t line;
8684 };
8685 
8686 /*
8687  *  String cache should ideally be at duk_hthread level, but that would
8688  *  cause string finalization to slow down relative to the number of
8689  *  threads; string finalization must check the string cache for "weak"
8690  *  references to the string being finalized to avoid dead pointers.
8691  *
8692  *  Thus, string caches are now at the heap level now.
8693  */
8694 
8695 struct duk_strcache_entry {
8696 	duk_hstring *h;
8697 	duk_uint32_t bidx;
8698 	duk_uint32_t cidx;
8699 };
8700 
8701 /*
8702  *  Longjmp state, contains the information needed to perform a longjmp.
8703  *  Longjmp related values are written to value1, value2, and iserror.
8704  */
8705 
8706 struct duk_ljstate {
8707 	duk_jmpbuf *jmpbuf_ptr;   /* current setjmp() catchpoint */
8708 	duk_small_uint_t type;    /* longjmp type */
8709 	duk_bool_t iserror;       /* isError flag for yield */
8710 	duk_tval value1;          /* 1st related value (type specific) */
8711 	duk_tval value2;          /* 2nd related value (type specific) */
8712 };
8713 
8714 #define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
8715 		DUK_ASSERT(heap != NULL); \
8716 		DUK_ASSERT(heap->lj.type == DUK_LJ_TYPE_UNKNOWN); \
8717 		DUK_ASSERT(heap->lj.iserror == 0); \
8718 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value1)); \
8719 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&heap->lj.value2)); \
8720 	} while (0)
8721 #define DUK_ASSERT_LJSTATE_SET(heap) do { \
8722 		DUK_ASSERT(heap != NULL); \
8723 		DUK_ASSERT(heap->lj.type != DUK_LJ_TYPE_UNKNOWN); \
8724 	} while (0)
8725 
8726 /*
8727  *  Literal intern cache
8728  */
8729 
8730 struct duk_litcache_entry {
8731 	const duk_uint8_t *addr;
8732 	duk_hstring *h;
8733 };
8734 
8735 /*
8736  *  Main heap structure
8737  */
8738 
8739 struct duk_heap {
8740 	duk_small_uint_t flags;
8741 
8742 	/* Allocator functions. */
8743 	duk_alloc_function alloc_func;
8744 	duk_realloc_function realloc_func;
8745 	duk_free_function free_func;
8746 
8747 	/* Heap udata, used for allocator functions but also for other heap
8748 	 * level callbacks like fatal function, pointer compression, etc.
8749 	 */
8750 	void *heap_udata;
8751 
8752 	/* Fatal error handling, called e.g. when a longjmp() is needed but
8753 	 * lj.jmpbuf_ptr is NULL.  fatal_func must never return; it's not
8754 	 * declared as "noreturn" because doing that for typedefs is a bit
8755 	 * challenging portability-wise.
8756 	 */
8757 	duk_fatal_function fatal_func;
8758 
8759 	/* Main list of allocated heap objects.  Objects are either here,
8760 	 * in finalize_list waiting for processing, or in refzero_list
8761 	 * temporarily while a DECREF refzero cascade finishes.
8762 	 */
8763 	duk_heaphdr *heap_allocated;
8764 
8765 	/* Temporary work list for freeing a cascade of objects when a DECREF
8766 	 * (or DECREF_NORZ) encounters a zero refcount.  Using a work list
8767 	 * allows fixed C stack size when refcounts go to zero for a chain of
8768 	 * objects.  Outside of DECREF this is always a NULL because DECREF is
8769 	 * processed without side effects (only memory free calls).
8770 	 */
8771 #if defined(DUK_USE_REFERENCE_COUNTING)
8772 	duk_heaphdr *refzero_list;
8773 #endif
8774 
8775 #if defined(DUK_USE_FINALIZER_SUPPORT)
8776 	/* Work list for objects to be finalized. */
8777 	duk_heaphdr *finalize_list;
8778 #if defined(DUK_USE_ASSERTIONS)
8779 	/* Object whose finalizer is executing right now (no nesting). */
8780 	duk_heaphdr *currently_finalizing;
8781 #endif
8782 #endif
8783 
8784 	/* Freelist for duk_activations and duk_catchers. */
8785 #if defined(DUK_USE_CACHE_ACTIVATION)
8786 	duk_activation *activation_free;
8787 #endif
8788 #if defined(DUK_USE_CACHE_CATCHER)
8789 	duk_catcher *catcher_free;
8790 #endif
8791 
8792 	/* Voluntary mark-and-sweep trigger counter.  Intentionally signed
8793 	 * because we continue decreasing the value when voluntary GC cannot
8794 	 * run.
8795 	 */
8796 #if defined(DUK_USE_VOLUNTARY_GC)
8797 	duk_int_t ms_trigger_counter;
8798 #endif
8799 
8800 	/* Mark-and-sweep recursion control: too deep recursion causes
8801 	 * multi-pass processing to avoid growing C stack without bound.
8802 	 */
8803 	duk_uint_t ms_recursion_depth;
8804 
8805 	/* Mark-and-sweep flags automatically active (used for critical sections). */
8806 	duk_small_uint_t ms_base_flags;
8807 
8808 	/* Mark-and-sweep running flag.  Prevents re-entry, and also causes
8809 	 * refzero events to be ignored (= objects won't be queued to refzero_list).
8810 	 */
8811 	duk_uint_t ms_running;
8812 
8813 	/* Mark-and-sweep prevent count, stacking.  Used to avoid M&S side
8814 	 * effects (besides finalizers which are controlled separately) such
8815 	 * as compacting the string table or object property tables.  This
8816 	 * is also bumped when ms_running is set to prevent recursive re-entry.
8817 	 * Can also be bumped when mark-and-sweep is not running.
8818 	 */
8819 	duk_uint_t ms_prevent_count;
8820 
8821 	/* Finalizer processing prevent count, stacking.  Bumped when finalizers
8822 	 * are processed to prevent recursive finalizer processing (first call site
8823 	 * processing finalizers handles all finalizers until the list is empty).
8824 	 * Can also be bumped explicitly to prevent finalizer execution.
8825 	 */
8826 	duk_uint_t pf_prevent_count;
8827 
8828 	/* When processing finalize_list, don't actually run finalizers but
8829 	 * queue finalizable objects back to heap_allocated as is.  This is
8830 	 * used during heap destruction to deal with finalizers that keep
8831 	 * on creating more finalizable garbage.
8832 	 */
8833 	duk_uint_t pf_skip_finalizers;
8834 
8835 #if defined(DUK_USE_ASSERTIONS)
8836 	/* Set when we're in a critical path where an error throw would cause
8837 	 * e.g. sandboxing/protected call violations or state corruption.  This
8838 	 * is just used for asserts.
8839 	 */
8840 	duk_bool_t error_not_allowed;
8841 #endif
8842 
8843 #if defined(DUK_USE_ASSERTIONS)
8844 	/* Set when heap is still being initialized, helps with writing
8845 	 * some assertions.
8846 	 */
8847 	duk_bool_t heap_initializing;
8848 #endif
8849 
8850 	/* Marker for detecting internal "double faults", errors thrown when
8851 	 * we're trying to create an error object, see duk_error_throw.c.
8852 	 */
8853 	duk_bool_t creating_error;
8854 
8855 	/* Marker for indicating we're calling a user error augmentation
8856 	 * (errCreate/errThrow) function.  Errors created/thrown during
8857 	 * such a call are not augmented.
8858 	 */
8859 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
8860 	duk_bool_t augmenting_error;
8861 #endif
8862 
8863 	/* Longjmp state. */
8864 	duk_ljstate lj;
8865 
8866 	/* Heap thread, used internally and for finalization. */
8867 	duk_hthread *heap_thread;
8868 
8869 	/* Current running thread. */
8870 	duk_hthread *curr_thread;
8871 
8872 	/* Heap level "stash" object (e.g., various reachability roots). */
8873 	duk_hobject *heap_object;
8874 
8875 	/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
8876 	duk_int_t call_recursion_depth;
8877 	duk_int_t call_recursion_limit;
8878 
8879 	/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
8880 	duk_uint32_t hash_seed;
8881 
8882 	/* Random number state for duk_util_tinyrandom.c. */
8883 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
8884 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
8885 	duk_uint32_t rnd_state;  /* State for Shamir's three-op algorithm */
8886 #else
8887 	duk_uint64_t rnd_state[2];  /* State for xoroshiro128+ */
8888 #endif
8889 #endif
8890 
8891 	/* Counter for unique local symbol creation. */
8892 	/* XXX: When 64-bit types are available, it would be more efficient to
8893 	 * use a duk_uint64_t at least for incrementing but maybe also for
8894 	 * string formatting in the Symbol constructor.
8895 	 */
8896 	duk_uint32_t sym_counter[2];
8897 
8898 	/* For manual debugging: instruction count based on executor and
8899 	 * interrupt counter book-keeping.  Inspect debug logs to see how
8900 	 * they match up.
8901 	 */
8902 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
8903 	duk_int_t inst_count_exec;
8904 	duk_int_t inst_count_interrupt;
8905 #endif
8906 
8907 	/* Debugger state. */
8908 #if defined(DUK_USE_DEBUGGER_SUPPORT)
8909 	/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
8910 	duk_debug_read_function dbg_read_cb;                /* required, NULL implies detached */
8911 	duk_debug_write_function dbg_write_cb;              /* required */
8912 	duk_debug_peek_function dbg_peek_cb;
8913 	duk_debug_read_flush_function dbg_read_flush_cb;
8914 	duk_debug_write_flush_function dbg_write_flush_cb;
8915 	duk_debug_request_function dbg_request_cb;
8916 	duk_debug_detached_function dbg_detached_cb;
8917 	void *dbg_udata;
8918 
8919 	/* The following are only relevant when debugger is attached. */
8920 	duk_bool_t dbg_processing;              /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
8921 	duk_bool_t dbg_state_dirty;             /* resend state next time executor is about to run */
8922 	duk_bool_t dbg_force_restart;           /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
8923 	duk_bool_t dbg_detaching;               /* debugger detaching; used to avoid calling detach handler recursively */
8924 	duk_small_uint_t dbg_pause_flags;       /* flags for automatic pause behavior */
8925 	duk_activation *dbg_pause_act;          /* activation related to pause behavior (pause on line change, function entry/exit) */
8926 	duk_uint32_t dbg_pause_startline;       /* starting line number for line change related pause behavior */
8927 	duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS];  /* breakpoints: [0,breakpoint_count[ gc reachable */
8928 	duk_small_uint_t dbg_breakpoint_count;
8929 	duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1];  /* currently active breakpoints: NULL term, borrowed pointers */
8930 	/* XXX: make active breakpoints actual copies instead of pointers? */
8931 
8932 	/* These are for rate limiting Status notifications and transport peeking. */
8933 	duk_uint_t dbg_exec_counter;            /* cumulative opcode execution count (overflows are OK) */
8934 	duk_uint_t dbg_last_counter;            /* value of dbg_exec_counter when we last did a Date-based check */
8935 	duk_double_t dbg_last_time;             /* time when status/peek was last done (Date-based rate limit) */
8936 
8937 	/* Used to support single-byte stream lookahead. */
8938 	duk_bool_t dbg_have_next_byte;
8939 	duk_uint8_t dbg_next_byte;
8940 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
8941 #if defined(DUK_USE_ASSERTIONS)
8942 	duk_bool_t dbg_calling_transport;       /* transport call in progress, calling into Duktape forbidden */
8943 #endif
8944 
8945 	/* String intern table (weak refs). */
8946 #if defined(DUK_USE_STRTAB_PTRCOMP)
8947 	duk_uint16_t *strtable16;
8948 #else
8949 	duk_hstring **strtable;
8950 #endif
8951 	duk_uint32_t st_mask;    /* mask for lookup, st_size - 1 */
8952 	duk_uint32_t st_size;    /* stringtable size */
8953 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
8954 	duk_uint32_t st_count;   /* string count for resize load factor checks */
8955 #endif
8956 	duk_bool_t st_resizing;  /* string table is being resized; avoid recursive resize */
8957 
8958 	/* String access cache (codepoint offset -> byte offset) for fast string
8959 	 * character looping; 'weak' reference which needs special handling in GC.
8960 	 */
8961 	duk_strcache_entry strcache[DUK_HEAP_STRCACHE_SIZE];
8962 
8963 #if defined(DUK_USE_LITCACHE_SIZE)
8964 	/* Literal intern cache.  When enabled, strings interned as literals
8965 	 * (e.g. duk_push_literal()) will be pinned and cached for the lifetime
8966 	 * of the heap.
8967 	 */
8968 	duk_litcache_entry litcache[DUK_USE_LITCACHE_SIZE];
8969 #endif
8970 
8971 	/* Built-in strings. */
8972 #if defined(DUK_USE_ROM_STRINGS)
8973 	/* No field needed when strings are in ROM. */
8974 #else
8975 #if defined(DUK_USE_HEAPPTR16)
8976 	duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS];
8977 #else
8978 	duk_hstring *strs[DUK_HEAP_NUM_STRINGS];
8979 #endif
8980 #endif
8981 
8982 	/* Stats. */
8983 #if defined(DUK_USE_DEBUG)
8984 	duk_int_t stats_exec_opcodes;
8985 	duk_int_t stats_exec_interrupt;
8986 	duk_int_t stats_exec_throw;
8987 	duk_int_t stats_call_all;
8988 	duk_int_t stats_call_tailcall;
8989 	duk_int_t stats_call_ecmatoecma;
8990 	duk_int_t stats_safecall_all;
8991 	duk_int_t stats_safecall_nothrow;
8992 	duk_int_t stats_safecall_throw;
8993 	duk_int_t stats_ms_try_count;
8994 	duk_int_t stats_ms_skip_count;
8995 	duk_int_t stats_ms_emergency_count;
8996 	duk_int_t stats_strtab_intern_hit;
8997 	duk_int_t stats_strtab_intern_miss;
8998 	duk_int_t stats_strtab_resize_check;
8999 	duk_int_t stats_strtab_resize_grow;
9000 	duk_int_t stats_strtab_resize_shrink;
9001 	duk_int_t stats_strtab_litcache_hit;
9002 	duk_int_t stats_strtab_litcache_miss;
9003 	duk_int_t stats_strtab_litcache_pin;
9004 	duk_int_t stats_object_realloc_props;
9005 	duk_int_t stats_object_abandon_array;
9006 	duk_int_t stats_getownpropdesc_count;
9007 	duk_int_t stats_getownpropdesc_hit;
9008 	duk_int_t stats_getownpropdesc_miss;
9009 	duk_int_t stats_getpropdesc_count;
9010 	duk_int_t stats_getpropdesc_hit;
9011 	duk_int_t stats_getpropdesc_miss;
9012 	duk_int_t stats_getprop_all;
9013 	duk_int_t stats_getprop_arrayidx;
9014 	duk_int_t stats_getprop_bufobjidx;
9015 	duk_int_t stats_getprop_bufferidx;
9016 	duk_int_t stats_getprop_bufferlen;
9017 	duk_int_t stats_getprop_stringidx;
9018 	duk_int_t stats_getprop_stringlen;
9019 	duk_int_t stats_getprop_proxy;
9020 	duk_int_t stats_getprop_arguments;
9021 	duk_int_t stats_putprop_all;
9022 	duk_int_t stats_putprop_arrayidx;
9023 	duk_int_t stats_putprop_bufobjidx;
9024 	duk_int_t stats_putprop_bufferidx;
9025 	duk_int_t stats_putprop_proxy;
9026 	duk_int_t stats_getvar_all;
9027 	duk_int_t stats_putvar_all;
9028 #endif
9029 };
9030 
9031 /*
9032  *  Prototypes
9033  */
9034 
9035 DUK_INTERNAL_DECL
9036 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
9037                          duk_realloc_function realloc_func,
9038                          duk_free_function free_func,
9039                          void *heap_udata,
9040                          duk_fatal_function fatal_func);
9041 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap);
9042 DUK_INTERNAL_DECL void duk_free_hobject(duk_heap *heap, duk_hobject *h);
9043 DUK_INTERNAL_DECL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h);
9044 DUK_INTERNAL_DECL void duk_free_hstring(duk_heap *heap, duk_hstring *h);
9045 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr);
9046 
9047 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9048 #if defined(DUK_USE_REFERENCE_COUNTING)
9049 DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr);
9050 #endif
9051 #if defined(DUK_USE_FINALIZER_SUPPORT)
9052 DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9053 DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr);
9054 #endif
9055 #if defined(DUK_USE_ASSERTIONS)
9056 DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr);
9057 #endif
9058 #if defined(DUK_USE_INTERRUPT_COUNTER)
9059 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr);
9060 #endif
9061 
9062 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen);
9063 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len);
9064 #if defined(DUK_USE_LITCACHE_SIZE)
9065 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen);
9066 #endif
9067 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val);
9068 DUK_INTERNAL_DECL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val);
9069 #if defined(DUK_USE_REFERENCE_COUNTING)
9070 DUK_INTERNAL_DECL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h);
9071 #endif
9072 DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev);
9073 DUK_INTERNAL_DECL void duk_heap_strtable_force_resize(duk_heap *heap);
9074 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap);
9075 #if defined(DUK_USE_DEBUG)
9076 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap);
9077 #endif
9078 
9079 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h);
9080 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset);
9081 
9082 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
9083 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size);
9084 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize);
9085 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr);
9086 #endif
9087 
9088 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size);
9089 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size);
9090 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size);
9091 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size);
9092 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize);
9093 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize);
9094 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr);
9095 
9096 DUK_INTERNAL_DECL void duk_heap_free_freelists(duk_heap *heap);
9097 
9098 #if defined(DUK_USE_FINALIZER_SUPPORT)
9099 DUK_INTERNAL_DECL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj);
9100 DUK_INTERNAL_DECL void duk_heap_process_finalize_list(duk_heap *heap);
9101 #endif  /* DUK_USE_FINALIZER_SUPPORT */
9102 
9103 DUK_INTERNAL_DECL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags);
9104 
9105 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len);
9106 
9107 #endif  /* DUK_HEAP_H_INCLUDED */
9108 /* #include duk_debugger.h */
9109 #line 1 "duk_debugger.h"
9110 #if !defined(DUK_DEBUGGER_H_INCLUDED)
9111 #define DUK_DEBUGGER_H_INCLUDED
9112 
9113 /* Debugger protocol version is defined in the public API header. */
9114 
9115 /* Initial bytes for markers. */
9116 #define DUK_DBG_IB_EOM                   0x00
9117 #define DUK_DBG_IB_REQUEST               0x01
9118 #define DUK_DBG_IB_REPLY                 0x02
9119 #define DUK_DBG_IB_ERROR                 0x03
9120 #define DUK_DBG_IB_NOTIFY                0x04
9121 
9122 /* Other initial bytes. */
9123 #define DUK_DBG_IB_INT4                  0x10
9124 #define DUK_DBG_IB_STR4                  0x11
9125 #define DUK_DBG_IB_STR2                  0x12
9126 #define DUK_DBG_IB_BUF4                  0x13
9127 #define DUK_DBG_IB_BUF2                  0x14
9128 #define DUK_DBG_IB_UNUSED                0x15
9129 #define DUK_DBG_IB_UNDEFINED             0x16
9130 #define DUK_DBG_IB_NULL                  0x17
9131 #define DUK_DBG_IB_TRUE                  0x18
9132 #define DUK_DBG_IB_FALSE                 0x19
9133 #define DUK_DBG_IB_NUMBER                0x1a
9134 #define DUK_DBG_IB_OBJECT                0x1b
9135 #define DUK_DBG_IB_POINTER               0x1c
9136 #define DUK_DBG_IB_LIGHTFUNC             0x1d
9137 #define DUK_DBG_IB_HEAPPTR               0x1e
9138 /* The short string/integer initial bytes starting from 0x60 don't have
9139  * defines now.
9140  */
9141 
9142 /* Error codes. */
9143 #define DUK_DBG_ERR_UNKNOWN              0x00
9144 #define DUK_DBG_ERR_UNSUPPORTED          0x01
9145 #define DUK_DBG_ERR_TOOMANY              0x02
9146 #define DUK_DBG_ERR_NOTFOUND             0x03
9147 #define DUK_DBG_ERR_APPLICATION          0x04
9148 
9149 /* Commands and notifys initiated by Duktape. */
9150 #define DUK_DBG_CMD_STATUS               0x01
9151 #define DUK_DBG_CMD_UNUSED_2             0x02  /* Duktape 1.x: print notify */
9152 #define DUK_DBG_CMD_UNUSED_3             0x03  /* Duktape 1.x: alert notify */
9153 #define DUK_DBG_CMD_UNUSED_4             0x04  /* Duktape 1.x: log notify */
9154 #define DUK_DBG_CMD_THROW                0x05
9155 #define DUK_DBG_CMD_DETACHING            0x06
9156 #define DUK_DBG_CMD_APPNOTIFY            0x07
9157 
9158 /* Commands initiated by debug client. */
9159 #define DUK_DBG_CMD_BASICINFO            0x10
9160 #define DUK_DBG_CMD_TRIGGERSTATUS        0x11
9161 #define DUK_DBG_CMD_PAUSE                0x12
9162 #define DUK_DBG_CMD_RESUME               0x13
9163 #define DUK_DBG_CMD_STEPINTO             0x14
9164 #define DUK_DBG_CMD_STEPOVER             0x15
9165 #define DUK_DBG_CMD_STEPOUT              0x16
9166 #define DUK_DBG_CMD_LISTBREAK            0x17
9167 #define DUK_DBG_CMD_ADDBREAK             0x18
9168 #define DUK_DBG_CMD_DELBREAK             0x19
9169 #define DUK_DBG_CMD_GETVAR               0x1a
9170 #define DUK_DBG_CMD_PUTVAR               0x1b
9171 #define DUK_DBG_CMD_GETCALLSTACK         0x1c
9172 #define DUK_DBG_CMD_GETLOCALS            0x1d
9173 #define DUK_DBG_CMD_EVAL                 0x1e
9174 #define DUK_DBG_CMD_DETACH               0x1f
9175 #define DUK_DBG_CMD_DUMPHEAP             0x20
9176 #define DUK_DBG_CMD_GETBYTECODE          0x21
9177 #define DUK_DBG_CMD_APPREQUEST           0x22
9178 #define DUK_DBG_CMD_GETHEAPOBJINFO       0x23
9179 #define DUK_DBG_CMD_GETOBJPROPDESC       0x24
9180 #define DUK_DBG_CMD_GETOBJPROPDESCRANGE  0x25
9181 
9182 /* The low 8 bits map directly to duk_hobject.h DUK_PROPDESC_FLAG_xxx.
9183  * The remaining flags are specific to the debugger.
9184  */
9185 #define DUK_DBG_PROPFLAG_SYMBOL          (1U << 8)
9186 #define DUK_DBG_PROPFLAG_HIDDEN          (1U << 9)
9187 
9188 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9189 DUK_INTERNAL_DECL void duk_debug_do_detach(duk_heap *heap);
9190 
9191 DUK_INTERNAL_DECL duk_bool_t duk_debug_read_peek(duk_hthread *thr);
9192 DUK_INTERNAL_DECL void duk_debug_write_flush(duk_hthread *thr);
9193 
9194 DUK_INTERNAL_DECL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length);
9195 DUK_INTERNAL_DECL void duk_debug_skip_byte(duk_hthread *thr);
9196 
9197 DUK_INTERNAL_DECL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length);
9198 DUK_INTERNAL_DECL duk_uint8_t duk_debug_read_byte(duk_hthread *thr);
9199 DUK_INTERNAL_DECL duk_int32_t duk_debug_read_int(duk_hthread *thr);
9200 DUK_INTERNAL_DECL duk_hstring *duk_debug_read_hstring(duk_hthread *thr);
9201 /* XXX: exposed duk_debug_read_pointer */
9202 /* XXX: exposed duk_debug_read_buffer */
9203 /* XXX: exposed duk_debug_read_hbuffer */
9204 #if 0
9205 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr);
9206 #endif
9207 #if defined(DUK_USE_DEBUGGER_INSPECT)
9208 DUK_INTERNAL_DECL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr);
9209 #endif
9210 DUK_INTERNAL_DECL duk_tval *duk_debug_read_tval(duk_hthread *thr);
9211 
9212 DUK_INTERNAL_DECL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length);
9213 DUK_INTERNAL_DECL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x);
9214 DUK_INTERNAL_DECL void duk_debug_write_unused(duk_hthread *thr);
9215 DUK_INTERNAL_DECL void duk_debug_write_undefined(duk_hthread *thr);
9216 #if defined(DUK_USE_DEBUGGER_INSPECT)
9217 DUK_INTERNAL_DECL void duk_debug_write_null(duk_hthread *thr);
9218 #endif
9219 DUK_INTERNAL_DECL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val);
9220 DUK_INTERNAL_DECL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x);
9221 DUK_INTERNAL_DECL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x);
9222 DUK_INTERNAL_DECL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length);
9223 DUK_INTERNAL_DECL void duk_debug_write_cstring(duk_hthread *thr, const char *data);
9224 DUK_INTERNAL_DECL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h);
9225 DUK_INTERNAL_DECL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length);
9226 DUK_INTERNAL_DECL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h);
9227 DUK_INTERNAL_DECL void duk_debug_write_pointer(duk_hthread *thr, void *ptr);
9228 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
9229 DUK_INTERNAL_DECL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h);
9230 #endif
9231 DUK_INTERNAL_DECL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj);
9232 DUK_INTERNAL_DECL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv);
9233 #if 0  /* unused */
9234 DUK_INTERNAL_DECL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command);
9235 #endif
9236 DUK_INTERNAL_DECL void duk_debug_write_reply(duk_hthread *thr);
9237 DUK_INTERNAL_DECL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg);
9238 DUK_INTERNAL_DECL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command);
9239 DUK_INTERNAL_DECL void duk_debug_write_eom(duk_hthread *thr);
9240 
9241 DUK_INTERNAL_DECL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr);
9242 DUK_INTERNAL_DECL void duk_debug_send_status(duk_hthread *thr);
9243 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
9244 DUK_INTERNAL_DECL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal);
9245 #endif
9246 
9247 DUK_INTERNAL_DECL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc);
9248 DUK_INTERNAL_DECL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block);
9249 
9250 DUK_INTERNAL_DECL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line);
9251 DUK_INTERNAL_DECL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index);
9252 
9253 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_attached(duk_heap *heap);
9254 DUK_INTERNAL_DECL duk_bool_t duk_debug_is_paused(duk_heap *heap);
9255 DUK_INTERNAL_DECL void duk_debug_set_paused(duk_heap *heap);
9256 DUK_INTERNAL_DECL void duk_debug_clear_paused(duk_heap *heap);
9257 DUK_INTERNAL_DECL void duk_debug_clear_pause_state(duk_heap *heap);
9258 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
9259 
9260 #endif  /* DUK_DEBUGGER_H_INCLUDED */
9261 /* #include duk_debug.h */
9262 #line 1 "duk_debug.h"
9263 /*
9264  *  Debugging macros, DUK_DPRINT() and its variants in particular.
9265  *
9266  *  DUK_DPRINT() allows formatted debug prints, and supports standard
9267  *  and Duktape specific formatters.  See duk_debug_vsnprintf.c for details.
9268  *
9269  *  DUK_D(x), DUK_DD(x), and DUK_DDD(x) are used together with log macros
9270  *  for technical reasons.  They are concretely used to hide 'x' from the
9271  *  compiler when the corresponding log level is disabled.  This allows
9272  *  clean builds on non-C99 compilers, at the cost of more verbose code.
9273  *  Examples:
9274  *
9275  *    DUK_D(DUK_DPRINT("foo"));
9276  *    DUK_DD(DUK_DDPRINT("foo"));
9277  *    DUK_DDD(DUK_DDDPRINT("foo"));
9278  *
9279  *  This approach is preferable to the old "double parentheses" hack because
9280  *  double parentheses make the C99 solution worse: __FILE__ and __LINE__ can
9281  *  no longer be added transparently without going through globals, which
9282  *  works poorly with threading.
9283  */
9284 
9285 #if !defined(DUK_DEBUG_H_INCLUDED)
9286 #define DUK_DEBUG_H_INCLUDED
9287 
9288 #if defined(DUK_USE_DEBUG)
9289 
9290 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9291 #define DUK_D(x) x
9292 #else
9293 #define DUK_D(x) do { } while (0) /* omit */
9294 #endif
9295 
9296 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9297 #define DUK_DD(x) x
9298 #else
9299 #define DUK_DD(x) do { } while (0) /* omit */
9300 #endif
9301 
9302 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9303 #define DUK_DDD(x) x
9304 #else
9305 #define DUK_DDD(x) do { } while (0) /* omit */
9306 #endif
9307 
9308 /*
9309  *  Exposed debug macros: debugging enabled
9310  */
9311 
9312 #if defined(DUK_USE_VARIADIC_MACROS)
9313 
9314 /* Note: combining __FILE__, __LINE__, and __func__ into fmt would be
9315  * possible compile time, but waste some space with shared function names.
9316  */
9317 #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__);
9318 
9319 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9320 #define DUK_DPRINT(...)          DUK__DEBUG_LOG(DUK_LEVEL_DEBUG, __VA_ARGS__)
9321 #else
9322 #define DUK_DPRINT(...)
9323 #endif
9324 
9325 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9326 #define DUK_DDPRINT(...)         DUK__DEBUG_LOG(DUK_LEVEL_DDEBUG, __VA_ARGS__)
9327 #else
9328 #define DUK_DDPRINT(...)
9329 #endif
9330 
9331 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9332 #define DUK_DDDPRINT(...)        DUK__DEBUG_LOG(DUK_LEVEL_DDDEBUG, __VA_ARGS__)
9333 #else
9334 #define DUK_DDDPRINT(...)
9335 #endif
9336 
9337 #else  /* DUK_USE_VARIADIC_MACROS */
9338 
9339 #define DUK__DEBUG_STASH(lev)    \
9340 	(void) DUK_SNPRINTF(duk_debug_file_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FILE_MACRO), \
9341 	(void) (duk_debug_file_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9342 	(void) (duk_debug_line_stash = (duk_int_t) DUK_LINE_MACRO), \
9343 	(void) DUK_SNPRINTF(duk_debug_func_stash, DUK_DEBUG_STASH_SIZE, "%s", (const char *) DUK_FUNC_MACRO), \
9344 	(void) (duk_debug_func_stash[DUK_DEBUG_STASH_SIZE - 1] = (char) 0), \
9345 	(void) (duk_debug_level_stash = (lev))
9346 
9347 /* Without variadic macros resort to comma expression trickery to handle debug
9348  * prints.  This generates a lot of harmless warnings.  These hacks are not
9349  * needed normally because DUK_D() and friends will hide the entire debug log
9350  * statement from the compiler.
9351  */
9352 
9353 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 0)
9354 #define DUK_DPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DEBUG), (void) duk_debug_log  /* args go here in parens */
9355 #else
9356 #define DUK_DPRINT  0 && /* args go here as a comma expression in parens */
9357 #endif
9358 
9359 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
9360 #define DUK_DDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDEBUG), (void) duk_debug_log  /* args go here in parens */
9361 #else
9362 #define DUK_DDPRINT  0 && /* args */
9363 #endif
9364 
9365 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
9366 #define DUK_DDDPRINT  DUK__DEBUG_STASH(DUK_LEVEL_DDDEBUG), (void) duk_debug_log  /* args go here in parens */
9367 #else
9368 #define DUK_DDDPRINT  0 && /* args */
9369 #endif
9370 
9371 #endif  /* DUK_USE_VARIADIC_MACROS */
9372 
9373 #else  /* DUK_USE_DEBUG */
9374 
9375 /*
9376  *  Exposed debug macros: debugging disabled
9377  */
9378 
9379 #define DUK_D(x) do { } while (0) /* omit */
9380 #define DUK_DD(x) do { } while (0) /* omit */
9381 #define DUK_DDD(x) do { } while (0) /* omit */
9382 
9383 #if defined(DUK_USE_VARIADIC_MACROS)
9384 
9385 #define DUK_DPRINT(...)
9386 #define DUK_DDPRINT(...)
9387 #define DUK_DDDPRINT(...)
9388 
9389 #else  /* DUK_USE_VARIADIC_MACROS */
9390 
9391 #define DUK_DPRINT    0 && /* args go here as a comma expression in parens */
9392 #define DUK_DDPRINT   0 && /* args */
9393 #define DUK_DDDPRINT  0 && /* args */
9394 
9395 #endif  /* DUK_USE_VARIADIC_MACROS */
9396 
9397 #endif  /* DUK_USE_DEBUG */
9398 
9399 /*
9400  *  Structs
9401  */
9402 
9403 #if defined(DUK_USE_DEBUG)
9404 struct duk_fixedbuffer {
9405 	duk_uint8_t *buffer;
9406 	duk_size_t length;
9407 	duk_size_t offset;
9408 	duk_bool_t truncated;
9409 };
9410 #endif
9411 
9412 /*
9413  *  Prototypes
9414  */
9415 
9416 #if defined(DUK_USE_DEBUG)
9417 DUK_INTERNAL_DECL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap);
9418 #if 0  /*unused*/
9419 DUK_INTERNAL_DECL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...);
9420 #endif
9421 DUK_INTERNAL_DECL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size);
9422 
9423 #if defined(DUK_USE_VARIADIC_MACROS)
9424 DUK_INTERNAL_DECL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...);
9425 #else  /* DUK_USE_VARIADIC_MACROS */
9426 /* parameter passing, not thread safe */
9427 #define DUK_DEBUG_STASH_SIZE  128
9428 #if !defined(DUK_SINGLE_FILE)
9429 DUK_INTERNAL_DECL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
9430 DUK_INTERNAL_DECL duk_int_t duk_debug_line_stash;
9431 DUK_INTERNAL_DECL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
9432 DUK_INTERNAL_DECL duk_int_t duk_debug_level_stash;
9433 #endif
9434 DUK_INTERNAL_DECL void duk_debug_log(const char *fmt, ...);
9435 #endif  /* DUK_USE_VARIADIC_MACROS */
9436 
9437 DUK_INTERNAL_DECL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length);
9438 DUK_INTERNAL_DECL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x);
9439 DUK_INTERNAL_DECL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x);
9440 DUK_INTERNAL_DECL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...);
9441 DUK_INTERNAL_DECL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size);
9442 DUK_INTERNAL_DECL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb);
9443 
9444 #endif  /* DUK_USE_DEBUG */
9445 
9446 #endif  /* DUK_DEBUG_H_INCLUDED */
9447 /* #include duk_error.h */
9448 #line 1 "duk_error.h"
9449 /*
9450  *  Error handling macros, assertion macro, error codes.
9451  *
9452  *  There are three types of 'errors':
9453  *
9454  *    1. Ordinary errors relative to a thread, cause a longjmp, catchable.
9455  *    2. Fatal errors relative to a heap, cause fatal handler to be called.
9456  *    3. Fatal errors without context, cause the default (not heap specific)
9457  *       fatal handler to be called.
9458  *
9459  *  Fatal errors without context are used by debug code such as assertions.
9460  *  By providing a fatal error handler for a Duktape heap, user code can
9461  *  avoid fatal errors without context in non-debug builds.
9462  */
9463 
9464 #if !defined(DUK_ERROR_H_INCLUDED)
9465 #define DUK_ERROR_H_INCLUDED
9466 
9467 /*
9468  *  Error codes: defined in duktape.h
9469  *
9470  *  Error codes are used as a shorthand to throw exceptions from inside
9471  *  the implementation.  The appropriate ECMAScript object is constructed
9472  *  based on the code.  ECMAScript code throws objects directly.  The error
9473  *  codes are defined in the public API header because they are also used
9474  *  by calling code.
9475  */
9476 
9477 /*
9478  *  Normal error
9479  *
9480  *  Normal error is thrown with a longjmp() through the current setjmp()
9481  *  catchpoint record in the duk_heap.  The 'curr_thread' of the duk_heap
9482  *  identifies the throwing thread.
9483  *
9484  *  Error formatting is usually unnecessary.  The error macros provide a
9485  *  zero argument version (no formatting) and separate macros for small
9486  *  argument counts.  Variadic macros are not used to avoid portability
9487  *  issues and avoid the need for stash-based workarounds when they're not
9488  *  available.  Vararg calls are avoided for non-formatted error calls
9489  *  because vararg call sites are larger than normal, and there are a lot
9490  *  of call sites with no formatting.
9491  *
9492  *  Note that special formatting provided by debug macros is NOT available.
9493  *
9494  *  The _RAW variants allow the caller to specify file and line.  This makes
9495  *  it easier to write checked calls which want to use the call site of the
9496  *  checked function, not the error macro call inside the checked function.
9497  */
9498 
9499 #if defined(DUK_USE_VERBOSE_ERRORS)
9500 
9501 /* Because there are quite many call sites, pack error code (require at most
9502  * 8-bit) into a single argument.
9503  */
9504 #define DUK_ERROR(thr,err,msg) do { \
9505 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9506 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9507 		duk_err_handle_error((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9508 	} while (0)
9509 #define DUK_ERROR_RAW(thr,file,line,err,msg) do { \
9510 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9511 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9512 		duk_err_handle_error((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (msg)); \
9513 	} while (0)
9514 
9515 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) do { \
9516 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9517 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9518 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9519 	} while (0)
9520 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) do { \
9521 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9522 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9523 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1)); \
9524 	} while (0)
9525 
9526 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) do { \
9527 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9528 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9529 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9530 	} while (0)
9531 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) do { \
9532 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9533 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9534 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2)); \
9535 	} while (0)
9536 
9537 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) do { \
9538 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9539 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9540 		duk_err_handle_error_fmt((thr), DUK_FILE_MACRO, (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9541 	} while (0)
9542 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) do { \
9543 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9544 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9545 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3)); \
9546 	} while (0)
9547 
9548 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) do { \
9549 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) DUK_LINE_MACRO; \
9550 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9551 		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)); \
9552 	} while (0)
9553 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) do { \
9554 		duk_errcode_t duk__err = (err); duk_int_t duk__line = (duk_int_t) (line); \
9555 		DUK_ASSERT(duk__err >= 0 && duk__err <= 0xff); DUK_ASSERT(duk__line >= 0 && duk__line <= 0x00ffffffL); \
9556 		duk_err_handle_error_fmt((thr), (file), (((duk_uint_t) duk__err) << 24) | ((duk_uint_t) duk__line), (fmt), (arg1), (arg2), (arg3), (arg4)); \
9557 	} while (0)
9558 
9559 #else  /* DUK_USE_VERBOSE_ERRORS */
9560 
9561 #define DUK_ERROR(thr,err,msg)                    duk_err_handle_error((thr), (err))
9562 #define DUK_ERROR_RAW(thr,file,line,err,msg)      duk_err_handle_error((thr), (err))
9563 
9564 #define DUK_ERROR_FMT1(thr,err,fmt,arg1) DUK_ERROR((thr),(err),(fmt))
9565 #define DUK_ERROR_RAW_FMT1(thr,file,line,err,fmt,arg1) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9566 
9567 #define DUK_ERROR_FMT2(thr,err,fmt,arg1,arg2) DUK_ERROR((thr),(err),(fmt))
9568 #define DUK_ERROR_RAW_FMT2(thr,file,line,err,fmt,arg1,arg2) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9569 
9570 #define DUK_ERROR_FMT3(thr,err,fmt,arg1,arg2,arg3) DUK_ERROR((thr),(err),(fmt))
9571 #define DUK_ERROR_RAW_FMT3(thr,file,line,err,fmt,arg1,arg2,arg3) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9572 
9573 #define DUK_ERROR_FMT4(thr,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR((thr),(err),(fmt))
9574 #define DUK_ERROR_RAW_FMT4(thr,file,line,err,fmt,arg1,arg2,arg3,arg4) DUK_ERROR_RAW((thr),(file),(line),(err),(fmt))
9575 
9576 #endif  /* DUK_USE_VERBOSE_ERRORS */
9577 
9578 /*
9579  *  Fatal error without context
9580  *
9581  *  The macro is an expression to make it compatible with DUK_ASSERT_EXPR().
9582  */
9583 
9584 #define DUK_FATAL_WITHOUT_CONTEXT(msg) \
9585 	duk_default_fatal_handler(NULL, (msg))
9586 
9587 /*
9588  *  Error throwing helpers
9589  *
9590  *  The goal is to provide verbose and configurable error messages.  Call
9591  *  sites should be clean in source code and compile to a small footprint.
9592  *  Small footprint is also useful for performance because small cold paths
9593  *  reduce code cache pressure.  Adding macros here only makes sense if there
9594  *  are enough call sites to get concrete benefits.
9595  *
9596  *  DUK_ERROR_xxx() macros are generic and can be used anywhere.
9597  *
9598  *  DUK_DCERROR_xxx() macros can only be used in Duktape/C functions where
9599  *  the "return DUK_RET_xxx;" shorthand is available for low memory targets.
9600  *  The DUK_DCERROR_xxx() macros always either throw or perform a
9601  *  'return DUK_RET_xxx' from the calling function.
9602  */
9603 
9604 #if defined(DUK_USE_VERBOSE_ERRORS)
9605 /* Verbose errors with key/value summaries (non-paranoid) or without key/value
9606  * summaries (paranoid, for some security sensitive environments), the paranoid
9607  * vs. non-paranoid distinction affects only a few specific errors.
9608  */
9609 #if defined(DUK_USE_PARANOID_ERRORS)
9610 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9611 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9612 	} while (0)
9613 #else  /* DUK_USE_PARANOID_ERRORS */
9614 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9615 		duk_err_require_type_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx), (expectname)); \
9616 	} while (0)
9617 #endif  /* DUK_USE_PARANOID_ERRORS */
9618 
9619 #define DUK_ERROR_INTERNAL(thr) do { \
9620 		duk_err_error_internal((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9621 	} while (0)
9622 #define DUK_DCERROR_INTERNAL(thr) do { \
9623 		DUK_ERROR_INTERNAL((thr)); \
9624 		return 0; \
9625 	} while (0)
9626 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9627 		duk_err_error_alloc_failed((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9628 	} while (0)
9629 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9630 		DUK_ERROR((thr), DUK_ERR_ERROR, DUK_STR_UNSUPPORTED); \
9631 	} while (0)
9632 #define DUK_ERROR_ERROR(thr,msg) do { \
9633 		duk_err_error((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9634 	} while (0)
9635 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9636 		duk_err_range_index((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (idx)); \
9637 	} while (0)
9638 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9639 		duk_err_range_push_beyond((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9640 	} while (0)
9641 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9642 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_ARGS); \
9643 	} while (0)
9644 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9645 		DUK_ERROR_RANGE_INVALID_ARGS((thr)); \
9646 		return 0; \
9647 	} while (0)
9648 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9649 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_COUNT); \
9650 	} while (0)
9651 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9652 		DUK_ERROR_RANGE_INVALID_COUNT((thr)); \
9653 		return 0; \
9654 	} while (0)
9655 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9656 		DUK_ERROR_RANGE((thr), DUK_STR_INVALID_LENGTH); \
9657 	} while (0)
9658 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9659 		DUK_ERROR_RANGE_INVALID_LENGTH((thr)); \
9660 		return 0; \
9661 	} while (0)
9662 #define DUK_ERROR_RANGE(thr,msg) do { \
9663 		duk_err_range((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO, (msg)); \
9664 	} while (0)
9665 #define DUK_ERROR_EVAL(thr,msg) do { \
9666 		DUK_ERROR((thr), DUK_ERR_EVAL_ERROR, (msg)); \
9667 	} while (0)
9668 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9669 		DUK_ERROR((thr), DUK_ERR_REFERENCE_ERROR, (msg)); \
9670 	} while (0)
9671 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9672 		DUK_ERROR((thr), DUK_ERR_SYNTAX_ERROR, (msg)); \
9673 	} while (0)
9674 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9675 		duk_err_type_invalid_args((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9676 	} while (0)
9677 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9678 		DUK_ERROR_TYPE_INVALID_ARGS((thr)); \
9679 		return 0; \
9680 	} while (0)
9681 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9682 		duk_err_type_invalid_state((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9683 	} while (0)
9684 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9685 		DUK_ERROR_TYPE_INVALID_STATE((thr)); \
9686 		return 0; \
9687 	} while (0)
9688 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9689 		duk_err_type_invalid_trap_result((thr), DUK_FILE_MACRO, (duk_int_t) DUK_LINE_MACRO); \
9690 	} while (0)
9691 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9692 		DUK_ERROR_TYPE((thr), DUK_STR_INVALID_TRAP_RESULT); \
9693 	} while (0)
9694 #define DUK_ERROR_TYPE(thr,msg) do { \
9695 		DUK_ERROR((thr), DUK_ERR_TYPE_ERROR, (msg)); \
9696 	} while (0)
9697 #define DUK_ERROR_URI(thr,msg) do { \
9698 		DUK_ERROR((thr), DUK_ERR_URI_ERROR, (msg)); \
9699 	} while (0)
9700 #else  /* DUK_USE_VERBOSE_ERRORS */
9701 /* Non-verbose errors for low memory targets: no file, line, or message. */
9702 
9703 #define DUK_ERROR_REQUIRE_TYPE_INDEX(thr,idx,expectname,lowmemstr) do { \
9704 		duk_err_type((thr)); \
9705 	} while (0)
9706 
9707 #define DUK_ERROR_INTERNAL(thr) do { \
9708 		duk_err_error((thr)); \
9709 	} while (0)
9710 #define DUK_DCERROR_INTERNAL(thr) do { \
9711 		DUK_UNREF((thr)); \
9712 		return DUK_RET_ERROR; \
9713 	} while (0)
9714 #define DUK_ERROR_ALLOC_FAILED(thr) do { \
9715 		duk_err_error((thr)); \
9716 	} while (0)
9717 #define DUK_ERROR_UNSUPPORTED(thr) do { \
9718 		duk_err_error((thr)); \
9719 	} while (0)
9720 #define DUK_ERROR_ERROR(thr,msg) do { \
9721 		duk_err_error((thr)); \
9722 	} while (0)
9723 #define DUK_ERROR_RANGE_INDEX(thr,idx) do { \
9724 		duk_err_range((thr)); \
9725 	} while (0)
9726 #define DUK_ERROR_RANGE_PUSH_BEYOND(thr) do { \
9727 		duk_err_range((thr)); \
9728 	} while (0)
9729 #define DUK_ERROR_RANGE_INVALID_ARGS(thr) do { \
9730 		duk_err_range((thr)); \
9731 	} while (0)
9732 #define DUK_DCERROR_RANGE_INVALID_ARGS(thr) do { \
9733 		DUK_UNREF((thr)); \
9734 		return DUK_RET_RANGE_ERROR; \
9735 	} while (0)
9736 #define DUK_ERROR_RANGE_INVALID_COUNT(thr) do { \
9737 		duk_err_range((thr)); \
9738 	} while (0)
9739 #define DUK_DCERROR_RANGE_INVALID_COUNT(thr) do { \
9740 		DUK_UNREF((thr)); \
9741 		return DUK_RET_RANGE_ERROR; \
9742 	} while (0)
9743 #define DUK_ERROR_RANGE_INVALID_LENGTH(thr) do { \
9744 		duk_err_range((thr)); \
9745 	} while (0)
9746 #define DUK_DCERROR_RANGE_INVALID_LENGTH(thr) do { \
9747 		DUK_UNREF((thr)); \
9748 		return DUK_RET_RANGE_ERROR; \
9749 	} while (0)
9750 #define DUK_ERROR_RANGE(thr,msg) do { \
9751 		duk_err_range((thr)); \
9752 	} while (0)
9753 #define DUK_ERROR_EVAL(thr,msg) do { \
9754 		duk_err_eval((thr)); \
9755 	} while (0)
9756 #define DUK_ERROR_REFERENCE(thr,msg) do { \
9757 		duk_err_reference((thr)); \
9758 	} while (0)
9759 #define DUK_ERROR_SYNTAX(thr,msg) do { \
9760 		duk_err_syntax((thr)); \
9761 	} while (0)
9762 #define DUK_ERROR_TYPE_INVALID_ARGS(thr) do { \
9763 		duk_err_type((thr)); \
9764 	} while (0)
9765 #define DUK_DCERROR_TYPE_INVALID_ARGS(thr) do { \
9766 		DUK_UNREF((thr)); \
9767 		return DUK_RET_TYPE_ERROR; \
9768 	} while (0)
9769 #define DUK_ERROR_TYPE_INVALID_STATE(thr) do { \
9770 		duk_err_type((thr)); \
9771 	} while (0)
9772 #define DUK_DCERROR_TYPE_INVALID_STATE(thr) do { \
9773 		duk_err_type((thr)); \
9774 	} while (0)
9775 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9776 		duk_err_type((thr)); \
9777 	} while (0)
9778 #define DUK_DCERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9779 		DUK_UNREF((thr)); \
9780 		return DUK_RET_TYPE_ERROR; \
9781 	} while (0)
9782 #define DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr) do { \
9783 		duk_err_type((thr)); \
9784 	} while (0)
9785 #define DUK_ERROR_TYPE(thr,msg) do { \
9786 		duk_err_type((thr)); \
9787 	} while (0)
9788 #define DUK_ERROR_URI(thr,msg) do { \
9789 		duk_err_uri((thr)); \
9790 	} while (0)
9791 #endif  /* DUK_USE_VERBOSE_ERRORS */
9792 
9793 /*
9794  *  Assert macro: failure causes a fatal error.
9795  *
9796  *  NOTE: since the assert macro doesn't take a heap/context argument, there's
9797  *  no way to look up a heap/context specific fatal error handler which may have
9798  *  been given by the application.  Instead, assertion failures always use the
9799  *  internal default fatal error handler; it can be replaced via duk_config.h
9800  *  and then applies to all Duktape heaps.
9801  */
9802 
9803 #if defined(DUK_USE_ASSERTIONS)
9804 
9805 /* The message should be a compile time constant without formatting (less risk);
9806  * we don't care about assertion text size because they're not used in production
9807  * builds.
9808  */
9809 #define DUK_ASSERT(x)  do { \
9810 	if (!(x)) { \
9811 		DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9812 			" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"); \
9813 	} \
9814 	} while (0)
9815 
9816 /* Assertion compatible inside a comma expression, evaluates to void. */
9817 #define DUK_ASSERT_EXPR(x) \
9818 	((void) ((x) ? 0 : (DUK_FATAL_WITHOUT_CONTEXT("assertion failed: " #x \
9819 				" (" DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO) ")"), 0)))
9820 
9821 #else  /* DUK_USE_ASSERTIONS */
9822 
9823 #define DUK_ASSERT(x)  do { /* assertion omitted */ } while (0)
9824 
9825 #define DUK_ASSERT_EXPR(x)  ((void) 0)
9826 
9827 #endif  /* DUK_USE_ASSERTIONS */
9828 
9829 /* this variant is used when an assert would generate a compile warning by
9830  * being always true (e.g. >= 0 comparison for an unsigned value
9831  */
9832 #define DUK_ASSERT_DISABLE(x)  do { /* assertion disabled */ } while (0)
9833 
9834 /*
9835  *  Assertion helpers
9836  */
9837 
9838 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
9839 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  do { \
9840 		DUK_ASSERT((h) == NULL || DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) (h)) > 0); \
9841 	} while (0)
9842 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)  do { \
9843 		if ((tv) != NULL && DUK_TVAL_IS_HEAP_ALLOCATED((tv))) { \
9844 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(DUK_TVAL_GET_HEAPHDR((tv))) > 0); \
9845 		} \
9846 	} while (0)
9847 #else
9848 #define DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(h)  /* no refcount check */
9849 #define DUK_ASSERT_REFCOUNT_NONZERO_TVAL(tv)    /* no refcount check */
9850 #endif
9851 
9852 #define DUK_ASSERT_TOP(ctx,n)  DUK_ASSERT((duk_idx_t) duk_get_top((ctx)) == (duk_idx_t) (n))
9853 
9854 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_PACKED_TVAL)
9855 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  do { \
9856 		duk_double_union duk__assert_tmp_du; \
9857 		duk__assert_tmp_du.d = (dval); \
9858 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&duk__assert_tmp_du)); \
9859 	} while (0)
9860 #else
9861 #define DUK_ASSERT_DOUBLE_IS_NORMALIZED(dval)  /* nop */
9862 #endif
9863 
9864 #define DUK_ASSERT_VS_SPACE(thr) \
9865 	DUK_ASSERT(thr->valstack_top < thr->valstack_end)
9866 
9867 /*
9868  *  Helper to initialize a memory area (e.g. struct) with garbage when
9869  *  assertions enabled.
9870  */
9871 
9872 #if defined(DUK_USE_ASSERTIONS)
9873 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do { \
9874 		duk_memset_unsafe((void *) (ptr), 0x5a, size); \
9875 	} while (0)
9876 #else
9877 #define DUK_ASSERT_SET_GARBAGE(ptr,size) do {} while (0)
9878 #endif
9879 
9880 /*
9881  *  Helper for valstack space
9882  *
9883  *  Caller of DUK_ASSERT_VALSTACK_SPACE() estimates the number of free stack entries
9884  *  required for its own use, and any child calls which are not (a) Duktape API calls
9885  *  or (b) Duktape calls which involve extending the valstack (e.g. getter call).
9886  */
9887 
9888 #define DUK_VALSTACK_ASSERT_EXTRA  5  /* this is added to checks to allow for Duktape
9889                                        * API calls in addition to function's own use
9890                                        */
9891 #if defined(DUK_USE_ASSERTIONS)
9892 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   do { \
9893 		DUK_ASSERT((thr) != NULL); \
9894 		DUK_ASSERT((thr)->valstack_end - (thr)->valstack_top >= (n) + DUK_VALSTACK_ASSERT_EXTRA); \
9895 	} while (0)
9896 #else
9897 #define DUK_ASSERT_VALSTACK_SPACE(thr,n)   /* no valstack space check */
9898 #endif
9899 
9900 /*
9901  *  Prototypes
9902  */
9903 
9904 #if defined(DUK_USE_VERBOSE_ERRORS)
9905 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));
9906 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, ...));
9907 #else  /* DUK_USE_VERBOSE_ERRORS */
9908 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code));
9909 #endif  /* DUK_USE_VERBOSE_ERRORS */
9910 
9911 #if defined(DUK_USE_VERBOSE_ERRORS)
9912 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));
9913 #else
9914 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code));
9915 #endif
9916 
9917 DUK_NORETURN(DUK_INTERNAL_DECL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc));
9918 
9919 #define DUK_AUGMENT_FLAG_NOBLAME_FILELINE  (1U << 0)  /* if set, don't blame C file/line for .fileName and .lineNumber */
9920 #define DUK_AUGMENT_FLAG_SKIP_ONE          (1U << 1)  /* if set, skip topmost activation in traceback construction */
9921 
9922 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
9923 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);
9924 #endif
9925 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
9926 DUK_INTERNAL_DECL void duk_err_augment_error_throw(duk_hthread *thr);
9927 #endif
9928 
9929 #if defined(DUK_USE_VERBOSE_ERRORS)
9930 #if defined(DUK_USE_PARANOID_ERRORS)
9931 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));
9932 #else
9933 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));
9934 #endif
9935 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9936 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9937 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9938 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx));
9939 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9940 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message));
9941 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9942 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9943 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber));
9944 #else  /* DUK_VERBOSE_ERRORS */
9945 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_error(duk_hthread *thr));
9946 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_range(duk_hthread *thr));
9947 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_eval(duk_hthread *thr));
9948 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_reference(duk_hthread *thr));
9949 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_syntax(duk_hthread *thr));
9950 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_type(duk_hthread *thr));
9951 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_uri(duk_hthread *thr));
9952 #endif /* DUK_VERBOSE_ERRORS */
9953 
9954 DUK_NORETURN(DUK_INTERNAL_DECL void duk_err_longjmp(duk_hthread *thr));
9955 
9956 DUK_NORETURN(DUK_INTERNAL_DECL void duk_default_fatal_handler(void *udata, const char *msg));
9957 
9958 DUK_INTERNAL_DECL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val);
9959 #if defined(DUK_USE_DEBUGGER_SUPPORT)
9960 DUK_INTERNAL_DECL void duk_err_check_debugger_integration(duk_hthread *thr);
9961 #endif
9962 
9963 DUK_INTERNAL_DECL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t err_code);
9964 
9965 #endif  /* DUK_ERROR_H_INCLUDED */
9966 /* #include duk_unicode.h */
9967 #line 1 "duk_unicode.h"
9968 /*
9969  *  Unicode helpers
9970  */
9971 
9972 #if !defined(DUK_UNICODE_H_INCLUDED)
9973 #define DUK_UNICODE_H_INCLUDED
9974 
9975 /*
9976  *  UTF-8 / XUTF-8 / CESU-8 constants
9977  */
9978 
9979 #define DUK_UNICODE_MAX_XUTF8_LENGTH      7   /* up to 36 bit codepoints */
9980 #define DUK_UNICODE_MAX_XUTF8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9981 #define DUK_UNICODE_MAX_CESU8_LENGTH      6   /* all codepoints up to U+10FFFF */
9982 #define DUK_UNICODE_MAX_CESU8_BMP_LENGTH  3   /* all codepoints up to U+FFFF */
9983 
9984 /*
9985  *  Useful Unicode codepoints
9986  *
9987  *  Integer constants must be signed to avoid unexpected coercions
9988  *  in comparisons.
9989  */
9990 
9991 #define DUK_UNICODE_CP_ZWNJ                   0x200cL  /* zero-width non-joiner */
9992 #define DUK_UNICODE_CP_ZWJ                    0x200dL  /* zero-width joiner */
9993 #define DUK_UNICODE_CP_REPLACEMENT_CHARACTER  0xfffdL  /* http://en.wikipedia.org/wiki/Replacement_character#Replacement_character */
9994 
9995 /*
9996  *  ASCII character constants
9997  *
9998  *  C character literals like 'x' have a platform specific value and do
9999  *  not match ASCII (UTF-8) values on e.g. EBCDIC platforms.  So, use
10000  *  these (admittedly awkward) constants instead.  These constants must
10001  *  also have signed values to avoid unexpected coercions in comparisons.
10002  *
10003  *  http://en.wikipedia.org/wiki/ASCII
10004  */
10005 
10006 #define DUK_ASC_NUL              0x00
10007 #define DUK_ASC_SOH              0x01
10008 #define DUK_ASC_STX              0x02
10009 #define DUK_ASC_ETX              0x03
10010 #define DUK_ASC_EOT              0x04
10011 #define DUK_ASC_ENQ              0x05
10012 #define DUK_ASC_ACK              0x06
10013 #define DUK_ASC_BEL              0x07
10014 #define DUK_ASC_BS               0x08
10015 #define DUK_ASC_HT               0x09
10016 #define DUK_ASC_LF               0x0a
10017 #define DUK_ASC_VT               0x0b
10018 #define DUK_ASC_FF               0x0c
10019 #define DUK_ASC_CR               0x0d
10020 #define DUK_ASC_SO               0x0e
10021 #define DUK_ASC_SI               0x0f
10022 #define DUK_ASC_DLE              0x10
10023 #define DUK_ASC_DC1              0x11
10024 #define DUK_ASC_DC2              0x12
10025 #define DUK_ASC_DC3              0x13
10026 #define DUK_ASC_DC4              0x14
10027 #define DUK_ASC_NAK              0x15
10028 #define DUK_ASC_SYN              0x16
10029 #define DUK_ASC_ETB              0x17
10030 #define DUK_ASC_CAN              0x18
10031 #define DUK_ASC_EM               0x19
10032 #define DUK_ASC_SUB              0x1a
10033 #define DUK_ASC_ESC              0x1b
10034 #define DUK_ASC_FS               0x1c
10035 #define DUK_ASC_GS               0x1d
10036 #define DUK_ASC_RS               0x1e
10037 #define DUK_ASC_US               0x1f
10038 #define DUK_ASC_SPACE            0x20
10039 #define DUK_ASC_EXCLAMATION      0x21
10040 #define DUK_ASC_DOUBLEQUOTE      0x22
10041 #define DUK_ASC_HASH             0x23
10042 #define DUK_ASC_DOLLAR           0x24
10043 #define DUK_ASC_PERCENT          0x25
10044 #define DUK_ASC_AMP              0x26
10045 #define DUK_ASC_SINGLEQUOTE      0x27
10046 #define DUK_ASC_LPAREN           0x28
10047 #define DUK_ASC_RPAREN           0x29
10048 #define DUK_ASC_STAR             0x2a
10049 #define DUK_ASC_PLUS             0x2b
10050 #define DUK_ASC_COMMA            0x2c
10051 #define DUK_ASC_MINUS            0x2d
10052 #define DUK_ASC_PERIOD           0x2e
10053 #define DUK_ASC_SLASH            0x2f
10054 #define DUK_ASC_0                0x30
10055 #define DUK_ASC_1                0x31
10056 #define DUK_ASC_2                0x32
10057 #define DUK_ASC_3                0x33
10058 #define DUK_ASC_4                0x34
10059 #define DUK_ASC_5                0x35
10060 #define DUK_ASC_6                0x36
10061 #define DUK_ASC_7                0x37
10062 #define DUK_ASC_8                0x38
10063 #define DUK_ASC_9                0x39
10064 #define DUK_ASC_COLON            0x3a
10065 #define DUK_ASC_SEMICOLON        0x3b
10066 #define DUK_ASC_LANGLE           0x3c
10067 #define DUK_ASC_EQUALS           0x3d
10068 #define DUK_ASC_RANGLE           0x3e
10069 #define DUK_ASC_QUESTION         0x3f
10070 #define DUK_ASC_ATSIGN           0x40
10071 #define DUK_ASC_UC_A             0x41
10072 #define DUK_ASC_UC_B             0x42
10073 #define DUK_ASC_UC_C             0x43
10074 #define DUK_ASC_UC_D             0x44
10075 #define DUK_ASC_UC_E             0x45
10076 #define DUK_ASC_UC_F             0x46
10077 #define DUK_ASC_UC_G             0x47
10078 #define DUK_ASC_UC_H             0x48
10079 #define DUK_ASC_UC_I             0x49
10080 #define DUK_ASC_UC_J             0x4a
10081 #define DUK_ASC_UC_K             0x4b
10082 #define DUK_ASC_UC_L             0x4c
10083 #define DUK_ASC_UC_M             0x4d
10084 #define DUK_ASC_UC_N             0x4e
10085 #define DUK_ASC_UC_O             0x4f
10086 #define DUK_ASC_UC_P             0x50
10087 #define DUK_ASC_UC_Q             0x51
10088 #define DUK_ASC_UC_R             0x52
10089 #define DUK_ASC_UC_S             0x53
10090 #define DUK_ASC_UC_T             0x54
10091 #define DUK_ASC_UC_U             0x55
10092 #define DUK_ASC_UC_V             0x56
10093 #define DUK_ASC_UC_W             0x57
10094 #define DUK_ASC_UC_X             0x58
10095 #define DUK_ASC_UC_Y             0x59
10096 #define DUK_ASC_UC_Z             0x5a
10097 #define DUK_ASC_LBRACKET         0x5b
10098 #define DUK_ASC_BACKSLASH        0x5c
10099 #define DUK_ASC_RBRACKET         0x5d
10100 #define DUK_ASC_CARET            0x5e
10101 #define DUK_ASC_UNDERSCORE       0x5f
10102 #define DUK_ASC_GRAVE            0x60
10103 #define DUK_ASC_LC_A             0x61
10104 #define DUK_ASC_LC_B             0x62
10105 #define DUK_ASC_LC_C             0x63
10106 #define DUK_ASC_LC_D             0x64
10107 #define DUK_ASC_LC_E             0x65
10108 #define DUK_ASC_LC_F             0x66
10109 #define DUK_ASC_LC_G             0x67
10110 #define DUK_ASC_LC_H             0x68
10111 #define DUK_ASC_LC_I             0x69
10112 #define DUK_ASC_LC_J             0x6a
10113 #define DUK_ASC_LC_K             0x6b
10114 #define DUK_ASC_LC_L             0x6c
10115 #define DUK_ASC_LC_M             0x6d
10116 #define DUK_ASC_LC_N             0x6e
10117 #define DUK_ASC_LC_O             0x6f
10118 #define DUK_ASC_LC_P             0x70
10119 #define DUK_ASC_LC_Q             0x71
10120 #define DUK_ASC_LC_R             0x72
10121 #define DUK_ASC_LC_S             0x73
10122 #define DUK_ASC_LC_T             0x74
10123 #define DUK_ASC_LC_U             0x75
10124 #define DUK_ASC_LC_V             0x76
10125 #define DUK_ASC_LC_W             0x77
10126 #define DUK_ASC_LC_X             0x78
10127 #define DUK_ASC_LC_Y             0x79
10128 #define DUK_ASC_LC_Z             0x7a
10129 #define DUK_ASC_LCURLY           0x7b
10130 #define DUK_ASC_PIPE             0x7c
10131 #define DUK_ASC_RCURLY           0x7d
10132 #define DUK_ASC_TILDE            0x7e
10133 #define DUK_ASC_DEL              0x7f
10134 
10135 /*
10136  *  Miscellaneous
10137  */
10138 
10139 /* Uppercase A is 0x41, lowercase a is 0x61; OR 0x20 to convert uppercase
10140  * to lowercase.
10141  */
10142 #define DUK_LOWERCASE_CHAR_ASCII(x)  ((x) | 0x20)
10143 
10144 /*
10145  *  Unicode tables
10146  */
10147 
10148 #if defined(DUK_USE_SOURCE_NONBMP)
10149 /*
10150  *  Automatically generated by extract_chars.py, do not edit!
10151  */
10152 
10153 extern const duk_uint8_t duk_unicode_ids_noa[1063];
10154 #else
10155 /*
10156  *  Automatically generated by extract_chars.py, do not edit!
10157  */
10158 
10159 extern const duk_uint8_t duk_unicode_ids_noabmp[626];
10160 #endif
10161 
10162 #if defined(DUK_USE_SOURCE_NONBMP)
10163 /*
10164  *  Automatically generated by extract_chars.py, do not edit!
10165  */
10166 
10167 extern const duk_uint8_t duk_unicode_ids_m_let_noa[42];
10168 #else
10169 /*
10170  *  Automatically generated by extract_chars.py, do not edit!
10171  */
10172 
10173 extern const duk_uint8_t duk_unicode_ids_m_let_noabmp[24];
10174 #endif
10175 
10176 #if defined(DUK_USE_SOURCE_NONBMP)
10177 /*
10178  *  Automatically generated by extract_chars.py, do not edit!
10179  */
10180 
10181 extern const duk_uint8_t duk_unicode_idp_m_ids_noa[549];
10182 #else
10183 /*
10184  *  Automatically generated by extract_chars.py, do not edit!
10185  */
10186 
10187 extern const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358];
10188 #endif
10189 
10190 /*
10191  *  Automatically generated by extract_caseconv.py, do not edit!
10192  */
10193 
10194 extern const duk_uint8_t duk_unicode_caseconv_uc[1386];
10195 extern const duk_uint8_t duk_unicode_caseconv_lc[680];
10196 
10197 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
10198 /*
10199  *  Automatically generated by extract_caseconv.py, do not edit!
10200  */
10201 
10202 extern const duk_uint16_t duk_unicode_re_canon_lookup[65536];
10203 #endif
10204 
10205 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
10206 /*
10207  *  Automatically generated by extract_caseconv.py, do not edit!
10208  */
10209 
10210 #define DUK_CANON_BITMAP_BLKSIZE                                      32
10211 #define DUK_CANON_BITMAP_BLKSHIFT                                     5
10212 #define DUK_CANON_BITMAP_BLKMASK                                      31
10213 extern const duk_uint8_t duk_unicode_re_canon_bitmap[256];
10214 #endif
10215 
10216 /*
10217  *  Extern
10218  */
10219 
10220 /* duk_unicode_support.c */
10221 #if !defined(DUK_SINGLE_FILE)
10222 DUK_INTERNAL_DECL const duk_uint8_t duk_unicode_xutf8_markers[7];
10223 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_digit[2];
10224 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_white[22];
10225 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_wordchar[8];
10226 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_digit[4];
10227 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_white[24];
10228 DUK_INTERNAL_DECL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10];
10229 DUK_INTERNAL_DECL const duk_int8_t duk_is_idchar_tab[128];
10230 #endif  /* !DUK_SINGLE_FILE */
10231 
10232 /*
10233  *  Prototypes
10234  */
10235 
10236 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp);
10237 #if defined(DUK_USE_ASSERTIONS)
10238 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp);
10239 #endif
10240 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out);
10241 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out);
10242 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);
10243 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);
10244 DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen);
10245 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp);
10246 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp);
10247 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp);
10248 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp);
10249 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp);
10250 DUK_INTERNAL_DECL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase);
10251 #if defined(DUK_USE_REGEXP_SUPPORT)
10252 DUK_INTERNAL_DECL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp);
10253 DUK_INTERNAL_DECL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t cp);
10254 #endif
10255 
10256 #endif  /* DUK_UNICODE_H_INCLUDED */
10257 /* #include duk_json.h */
10258 #line 1 "duk_json.h"
10259 /*
10260  *  Defines for JSON, especially duk_bi_json.c.
10261  */
10262 
10263 #if !defined(DUK_JSON_H_INCLUDED)
10264 #define DUK_JSON_H_INCLUDED
10265 
10266 /* Encoding/decoding flags */
10267 #define DUK_JSON_FLAG_ASCII_ONLY              (1U << 0)  /* escape any non-ASCII characters */
10268 #define DUK_JSON_FLAG_AVOID_KEY_QUOTES        (1U << 1)  /* avoid key quotes when key is an ASCII Identifier */
10269 #define DUK_JSON_FLAG_EXT_CUSTOM              (1U << 2)  /* extended types: custom encoding */
10270 #define DUK_JSON_FLAG_EXT_COMPATIBLE          (1U << 3)  /* extended types: compatible encoding */
10271 
10272 /* How much stack to require on entry to object/array encode */
10273 #define DUK_JSON_ENC_REQSTACK                 32
10274 
10275 /* How much stack to require on entry to object/array decode */
10276 #define DUK_JSON_DEC_REQSTACK                 32
10277 
10278 /* How large a loop detection stack to use */
10279 #define DUK_JSON_ENC_LOOPARRAY                64
10280 
10281 /* Encoding state.  Heap object references are all borrowed. */
10282 typedef struct {
10283 	duk_hthread *thr;
10284 	duk_bufwriter_ctx bw;        /* output bufwriter */
10285 	duk_hobject *h_replacer;     /* replacer function */
10286 	duk_hstring *h_gap;          /* gap (if empty string, NULL) */
10287 	duk_idx_t idx_proplist;      /* explicit PropertyList */
10288 	duk_idx_t idx_loop;          /* valstack index of loop detection object */
10289 	duk_small_uint_t flags;
10290 	duk_small_uint_t flag_ascii_only;
10291 	duk_small_uint_t flag_avoid_key_quotes;
10292 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10293 	duk_small_uint_t flag_ext_custom;
10294 	duk_small_uint_t flag_ext_compatible;
10295 	duk_small_uint_t flag_ext_custom_or_compatible;
10296 #endif
10297 	duk_uint_t recursion_depth;
10298 	duk_uint_t recursion_limit;
10299 	duk_uint_t mask_for_undefined;      /* type bit mask: types which certainly produce 'undefined' */
10300 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10301 	duk_small_uint_t stridx_custom_undefined;
10302 	duk_small_uint_t stridx_custom_nan;
10303 	duk_small_uint_t stridx_custom_neginf;
10304 	duk_small_uint_t stridx_custom_posinf;
10305 	duk_small_uint_t stridx_custom_function;
10306 #endif
10307 	duk_hobject *visiting[DUK_JSON_ENC_LOOPARRAY];  /* indexed by recursion_depth */
10308 } duk_json_enc_ctx;
10309 
10310 typedef struct {
10311 	duk_hthread *thr;
10312 	const duk_uint8_t *p;
10313 	const duk_uint8_t *p_start;
10314 	const duk_uint8_t *p_end;
10315 	duk_idx_t idx_reviver;
10316 	duk_small_uint_t flags;
10317 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
10318 	duk_small_uint_t flag_ext_custom;
10319 	duk_small_uint_t flag_ext_compatible;
10320 	duk_small_uint_t flag_ext_custom_or_compatible;
10321 #endif
10322 	duk_int_t recursion_depth;
10323 	duk_int_t recursion_limit;
10324 } duk_json_dec_ctx;
10325 
10326 #endif  /* DUK_JSON_H_INCLUDED */
10327 /* #include duk_js.h */
10328 #line 1 "duk_js.h"
10329 /*
10330  *  ECMAScript execution, support primitives.
10331  */
10332 
10333 #if !defined(DUK_JS_H_INCLUDED)
10334 #define DUK_JS_H_INCLUDED
10335 
10336 /* Flags for call handling.  Lowest flags must match bytecode DUK_BC_CALL_FLAG_xxx 1:1. */
10337 #define DUK_CALL_FLAG_TAILCALL                 (1U << 0)  /* setup for a tail call */
10338 #define DUK_CALL_FLAG_CONSTRUCT                (1U << 1)  /* constructor call (i.e. called as 'new Foo()') */
10339 #define DUK_CALL_FLAG_CALLED_AS_EVAL           (1U << 2)  /* call was made using the identifier 'eval' */
10340 #define DUK_CALL_FLAG_ALLOW_ECMATOECMA         (1U << 3)  /* ecma-to-ecma call with executor reuse is possible */
10341 #define DUK_CALL_FLAG_DIRECT_EVAL              (1U << 4)  /* call is a direct eval call */
10342 #define DUK_CALL_FLAG_CONSTRUCT_PROXY          (1U << 5)  /* handled via 'construct' proxy trap, check return value invariant(s) */
10343 #define DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED (1U << 6)  /* prototype of 'default instance' updated, temporary flag in call handling */
10344 
10345 /* Flags for duk_js_equals_helper(). */
10346 #define DUK_EQUALS_FLAG_SAMEVALUE            (1U << 0)  /* use SameValue instead of non-strict equality */
10347 #define DUK_EQUALS_FLAG_STRICT               (1U << 1)  /* use strict equality instead of non-strict equality */
10348 
10349 /* Flags for duk_js_compare_helper(). */
10350 #define DUK_COMPARE_FLAG_NEGATE              (1U << 0)  /* negate result */
10351 #define DUK_COMPARE_FLAG_EVAL_LEFT_FIRST     (1U << 1)  /* eval left argument first */
10352 
10353 /* conversions, coercions, comparison, etc */
10354 DUK_INTERNAL_DECL duk_bool_t duk_js_toboolean(duk_tval *tv);
10355 DUK_INTERNAL_DECL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv);
10356 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger_number(duk_double_t x);
10357 DUK_INTERNAL_DECL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv);
10358 DUK_INTERNAL_DECL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv);
10359 DUK_INTERNAL_DECL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv);
10360 DUK_INTERNAL_DECL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv);
10361 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen);
10362 #if !defined(DUK_USE_HSTRING_ARRIDX)
10363 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h);
10364 DUK_INTERNAL_DECL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h);
10365 #endif
10366 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);
10367 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);
10368 DUK_INTERNAL_DECL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2);
10369 #if 0  /* unused */
10370 DUK_INTERNAL_DECL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2);
10371 #endif
10372 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);
10373 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10374 #if defined(DUK_USE_SYMBOL_BUILTIN)
10375 DUK_INTERNAL_DECL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10376 #endif
10377 DUK_INTERNAL_DECL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y);
10378 DUK_INTERNAL_DECL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x);
10379 
10380 /* arithmetic */
10381 DUK_INTERNAL_DECL double duk_js_arith_pow(double x, double y);
10382 DUK_INTERNAL_DECL double duk_js_arith_mod(double x, double y);
10383 
10384 #define duk_js_equals(thr,tv_x,tv_y) \
10385 	duk_js_equals_helper((thr), (tv_x), (tv_y), 0)
10386 #define duk_js_strict_equals(tv_x,tv_y) \
10387 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_STRICT)
10388 #define duk_js_samevalue(tv_x,tv_y) \
10389 	duk_js_equals_helper(NULL, (tv_x), (tv_y), DUK_EQUALS_FLAG_SAMEVALUE)
10390 
10391 /* E5 Sections 11.8.1, 11.8.5; x < y */
10392 #define duk_js_lessthan(thr,tv_x,tv_y) \
10393 	duk_js_compare_helper((thr), (tv_x), (tv_Y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
10394 
10395 /* E5 Sections 11.8.2, 11.8.5; x > y  -->  y < x */
10396 #define duk_js_greaterthan(thr,tv_x,tv_y) \
10397 	duk_js_compare_helper((thr), (tv_y), (tv_x), 0)
10398 
10399 /* E5 Sections 11.8.3, 11.8.5; x <= y  -->  not (x > y)  -->  not (y < x) */
10400 #define duk_js_lessthanorequal(thr,tv_x,tv_y) \
10401 	duk_js_compare_helper((thr), (tv_y), (tv_x), DUK_COMPARE_FLAG_NEGATE)
10402 
10403 /* E5 Sections 11.8.4, 11.8.5; x >= y  -->  not (x < y) */
10404 #define duk_js_greaterthanorequal(thr,tv_x,tv_y) \
10405 	duk_js_compare_helper((thr), (tv_x), (tv_y), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
10406 
10407 /* identifiers and environment handling */
10408 #if 0  /*unused*/
10409 DUK_INTERNAL duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10410 #endif
10411 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_bool_t throw_flag);
10412 DUK_INTERNAL_DECL duk_bool_t duk_js_getvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_bool_t throw_flag);
10413 DUK_INTERNAL_DECL void duk_js_putvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10414 DUK_INTERNAL_DECL void duk_js_putvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name, duk_tval *val, duk_bool_t strict);
10415 #if 0  /*unused*/
10416 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_envrec(duk_hthread *thr, duk_hobject *env, duk_hstring *name);
10417 #endif
10418 DUK_INTERNAL_DECL duk_bool_t duk_js_delvar_activation(duk_hthread *thr, duk_activation *act, duk_hstring *name);
10419 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);
10420 DUK_INTERNAL_DECL void duk_js_init_activation_environment_records_delayed(duk_hthread *thr, duk_activation *act);
10421 DUK_INTERNAL_DECL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env);
10422 DUK_INTERNAL_DECL duk_hobject *duk_create_activation_environment_record(duk_hthread *thr, duk_hobject *func, duk_size_t bottom_byteoff);
10423 DUK_INTERNAL_DECL void duk_js_push_closure(duk_hthread *thr,
10424                                            duk_hcompfunc *fun_temp,
10425                                            duk_hobject *outer_var_env,
10426                                            duk_hobject *outer_lex_env,
10427                                            duk_bool_t add_auto_proto);
10428 
10429 /* call handling */
10430 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected(duk_hthread *thr, duk_idx_t idx_func, duk_small_uint_t call_flags);
10431 DUK_INTERNAL_DECL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags);
10432 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);
10433 DUK_INTERNAL_DECL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant);
10434 #if defined(DUK_USE_VERBOSE_ERRORS)
10435 DUK_INTERNAL_DECL void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key);
10436 #endif
10437 
10438 /* bytecode execution */
10439 DUK_INTERNAL_DECL void duk_js_execute_bytecode(duk_hthread *exec_thr);
10440 
10441 #endif  /* DUK_JS_H_INCLUDED */
10442 /* #include duk_numconv.h */
10443 #line 1 "duk_numconv.h"
10444 /*
10445  *  Number-to-string conversion.  The semantics of these is very tightly
10446  *  bound with the ECMAScript semantics required for call sites.
10447  */
10448 
10449 #if !defined(DUK_NUMCONV_H_INCLUDED)
10450 #define DUK_NUMCONV_H_INCLUDED
10451 
10452 /* Output a specified number of digits instead of using the shortest
10453  * form.  Used for toPrecision() and toFixed().
10454  */
10455 #define DUK_N2S_FLAG_FIXED_FORMAT         (1U << 0)
10456 
10457 /* Force exponential format.  Used for toExponential(). */
10458 #define DUK_N2S_FLAG_FORCE_EXP            (1U << 1)
10459 
10460 /* If number would need zero padding (for whole number part), use
10461  * exponential format instead.  E.g. if input number is 12300, 3
10462  * digits are generated ("123"), output "1.23e+4" instead of "12300".
10463  * Used for toPrecision().
10464  */
10465 #define DUK_N2S_FLAG_NO_ZERO_PAD          (1U << 2)
10466 
10467 /* Digit count indicates number of fractions (i.e. an absolute
10468  * digit index instead of a relative one).  Used together with
10469  * DUK_N2S_FLAG_FIXED_FORMAT for toFixed().
10470  */
10471 #define DUK_N2S_FLAG_FRACTION_DIGITS      (1U << 3)
10472 
10473 /*
10474  *  String-to-number conversion
10475  */
10476 
10477 /* Maximum exponent value when parsing numbers.  This is not strictly
10478  * compliant as there should be no upper limit, but as we parse the
10479  * exponent without a bigint, impose some limit.  The limit should be
10480  * small enough that multiplying it (or limit-1 to be precise) won't
10481  * overflow signed 32-bit integer range.  Exponent is only parsed with
10482  * radix 10, but with maximum radix (36) a safe limit is:
10483  * (10000000*36).toString(16) -> '15752a00'
10484  */
10485 #define DUK_S2N_MAX_EXPONENT              10000000L
10486 
10487 /* Trim white space (= allow leading and trailing whitespace) */
10488 #define DUK_S2N_FLAG_TRIM_WHITE           (1U << 0)
10489 
10490 /* Allow exponent */
10491 #define DUK_S2N_FLAG_ALLOW_EXP            (1U << 1)
10492 
10493 /* Allow trailing garbage (e.g. treat "123foo" as "123) */
10494 #define DUK_S2N_FLAG_ALLOW_GARBAGE        (1U << 2)
10495 
10496 /* Allow leading plus sign */
10497 #define DUK_S2N_FLAG_ALLOW_PLUS           (1U << 3)
10498 
10499 /* Allow leading minus sign */
10500 #define DUK_S2N_FLAG_ALLOW_MINUS          (1U << 4)
10501 
10502 /* Allow 'Infinity' */
10503 #define DUK_S2N_FLAG_ALLOW_INF            (1U << 5)
10504 
10505 /* Allow fraction part */
10506 #define DUK_S2N_FLAG_ALLOW_FRAC           (1U << 6)
10507 
10508 /* Allow naked fraction (e.g. ".123") */
10509 #define DUK_S2N_FLAG_ALLOW_NAKED_FRAC     (1U << 7)
10510 
10511 /* Allow empty fraction (e.g. "123.") */
10512 #define DUK_S2N_FLAG_ALLOW_EMPTY_FRAC     (1U << 8)
10513 
10514 /* Allow empty string to be interpreted as 0 */
10515 #define DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO  (1U << 9)
10516 
10517 /* Allow leading zeroes (e.g. "0123" -> "123") */
10518 #define DUK_S2N_FLAG_ALLOW_LEADING_ZERO   (1U << 10)
10519 
10520 /* Allow automatic detection of hex base ("0x" or "0X" prefix),
10521  * overrides radix argument and forces integer mode.
10522  */
10523 #define DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT   (1U << 11)
10524 
10525 /* Allow automatic detection of legacy octal base ("0n"),
10526  * overrides radix argument and forces integer mode.
10527  */
10528 #define DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT   (1U << 12)
10529 
10530 /* Allow automatic detection of ES2015 octal base ("0o123"),
10531  * overrides radix argument and forces integer mode.
10532  */
10533 #define DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT   (1U << 13)
10534 
10535 /* Allow automatic detection of ES2015 binary base ("0b10001"),
10536  * overrides radix argument and forces integer mode.
10537  */
10538 #define DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT   (1U << 14)
10539 
10540 /*
10541  *  Prototypes
10542  */
10543 
10544 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);
10545 DUK_INTERNAL_DECL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags);
10546 
10547 #endif  /* DUK_NUMCONV_H_INCLUDED */
10548 /* #include duk_bi_protos.h */
10549 #line 1 "duk_bi_protos.h"
10550 /*
10551  *  Prototypes for built-in functions not automatically covered by the
10552  *  header declarations emitted by genbuiltins.py.
10553  */
10554 
10555 #if !defined(DUK_BUILTIN_PROTOS_H_INCLUDED)
10556 #define DUK_BUILTIN_PROTOS_H_INCLUDED
10557 
10558 /* Buffer size needed for ISO 8601 formatting.
10559  * Accurate value is 32 + 1 for NUL termination:
10560  *   >>> len('+123456-01-23T12:34:56.123+12:34')
10561  *   32
10562  * Include additional space to be safe.
10563  */
10564 #define  DUK_BI_DATE_ISO8601_BUFSIZE  40
10565 
10566 /* Helpers exposed for internal use */
10567 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);
10568 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags);
10569 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year);
10570 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x);
10571 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t year);
10572 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x);
10573 /* Built-in providers */
10574 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
10575 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_gettimeofday(void);
10576 #endif
10577 #if defined(DUK_USE_DATE_NOW_TIME)
10578 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_time(void);
10579 #endif
10580 #if defined(DUK_USE_DATE_NOW_WINDOWS)
10581 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows(void);
10582 #endif
10583 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
10584 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_now_windows_subms(void);
10585 #endif
10586 #if defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S) || defined(DUK_USE_DATE_TZO_GMTIME)
10587 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d);
10588 #endif
10589 #if defined(DUK_USE_DATE_TZO_WINDOWS)
10590 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d);
10591 #endif
10592 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
10593 DUK_INTERNAL_DECL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d);
10594 #endif
10595 #if defined(DUK_USE_DATE_PRS_STRPTIME)
10596 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str);
10597 #endif
10598 #if defined(DUK_USE_DATE_PRS_GETDATE)
10599 DUK_INTERNAL_DECL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str);
10600 #endif
10601 #if defined(DUK_USE_DATE_FMT_STRFTIME)
10602 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);
10603 #endif
10604 
10605 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
10606 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void);
10607 #endif
10608 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
10609 DUK_INTERNAL_DECL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void);
10610 #endif
10611 
10612 DUK_INTERNAL_DECL
10613 void duk_bi_json_parse_helper(duk_hthread *thr,
10614                               duk_idx_t idx_value,
10615                               duk_idx_t idx_reviver,
10616                               duk_small_uint_t flags);
10617 DUK_INTERNAL_DECL
10618 void duk_bi_json_stringify_helper(duk_hthread *thr,
10619                                   duk_idx_t idx_value,
10620                                   duk_idx_t idx_replacer,
10621                                   duk_idx_t idx_space,
10622                                   duk_small_uint_t flags);
10623 
10624 DUK_INTERNAL_DECL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr);
10625 
10626 #if defined(DUK_USE_ES6_PROXY)
10627 DUK_INTERNAL_DECL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags);
10628 #endif
10629 
10630 #endif  /* DUK_BUILTIN_PROTOS_H_INCLUDED */
10631 /* #include duk_selftest.h */
10632 #line 1 "duk_selftest.h"
10633 /*
10634  *  Selftest code
10635  */
10636 
10637 #if !defined(DUK_SELFTEST_H_INCLUDED)
10638 #define DUK_SELFTEST_H_INCLUDED
10639 
10640 #if defined(DUK_USE_SELF_TESTS)
10641 DUK_INTERNAL_DECL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
10642                                                     duk_realloc_function realloc_func,
10643                                                     duk_free_function free_func,
10644                                                     void *udata);
10645 #endif
10646 
10647 #endif  /* DUK_SELFTEST_H_INCLUDED */
10648 #line 82 "duk_internal.h"
10649 
10650 #endif  /* DUK_INTERNAL_H_INCLUDED */
10651 #line 10 "duk_replacements.c"
10652 
10653 #if defined(DUK_USE_COMPUTED_NAN)
10654 DUK_INTERNAL double duk_computed_nan;
10655 #endif
10656 
10657 #if defined(DUK_USE_COMPUTED_INFINITY)
10658 DUK_INTERNAL double duk_computed_infinity;
10659 #endif
10660 
10661 #if defined(DUK_USE_REPL_FPCLASSIFY)
duk_repl_fpclassify(double x)10662 DUK_INTERNAL int duk_repl_fpclassify(double x) {
10663 	duk_double_union u;
10664 	duk_uint_fast16_t expt;
10665 	duk_small_int_t mzero;
10666 
10667 	u.d = x;
10668 	expt = (duk_uint_fast16_t) (u.us[DUK_DBL_IDX_US0] & 0x7ff0UL);
10669 	if (expt > 0x0000UL && expt < 0x7ff0UL) {
10670 		/* expt values [0x001,0x7fe] = normal */
10671 		return DUK_FP_NORMAL;
10672 	}
10673 
10674 	mzero = (u.ui[DUK_DBL_IDX_UI1] == 0 && (u.ui[DUK_DBL_IDX_UI0] & 0x000fffffUL) == 0);
10675 	if (expt == 0x0000UL) {
10676 		/* expt 0x000 is zero/subnormal */
10677 		if (mzero) {
10678 			return DUK_FP_ZERO;
10679 		} else {
10680 			return DUK_FP_SUBNORMAL;
10681 		}
10682 	} else {
10683 		/* expt 0xfff is infinite/nan */
10684 		if (mzero) {
10685 			return DUK_FP_INFINITE;
10686 		} else {
10687 			return DUK_FP_NAN;
10688 		}
10689 	}
10690 }
10691 #endif
10692 
10693 #if defined(DUK_USE_REPL_SIGNBIT)
duk_repl_signbit(double x)10694 DUK_INTERNAL int duk_repl_signbit(double x) {
10695 	duk_double_union u;
10696 	u.d = x;
10697 	return (int) (u.uc[DUK_DBL_IDX_UC0] & 0x80UL);
10698 }
10699 #endif
10700 
10701 #if defined(DUK_USE_REPL_ISFINITE)
duk_repl_isfinite(double x)10702 DUK_INTERNAL int duk_repl_isfinite(double x) {
10703 	int c = DUK_FPCLASSIFY(x);
10704 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
10705 		return 0;
10706 	} else {
10707 		return 1;
10708 	}
10709 }
10710 #endif
10711 
10712 #if defined(DUK_USE_REPL_ISNAN)
duk_repl_isnan(double x)10713 DUK_INTERNAL int duk_repl_isnan(double x) {
10714 	int c = DUK_FPCLASSIFY(x);
10715 	return (c == DUK_FP_NAN);
10716 }
10717 #endif
10718 
10719 #if defined(DUK_USE_REPL_ISINF)
duk_repl_isinf(double x)10720 DUK_INTERNAL int duk_repl_isinf(double x) {
10721 	int c = DUK_FPCLASSIFY(x);
10722 	return (c == DUK_FP_INFINITE);
10723 }
10724 #endif
10725 #line 1 "duk_debug_macros.c"
10726 /*
10727  *  Debugging macro calls.
10728  */
10729 
10730 /* #include duk_internal.h -> already included */
10731 
10732 #if defined(DUK_USE_DEBUG)
10733 
10734 /*
10735  *  Debugging enabled
10736  */
10737 
10738 #include <stdio.h>
10739 #include <stdlib.h>
10740 #include <stdarg.h>
10741 
10742 #if !defined(DUK_USE_DEBUG_WRITE)
10743 #error debugging enabled (DUK_USE_DEBUG) but DUK_USE_DEBUG_WRITE not defined
10744 #endif
10745 
10746 #define DUK__DEBUG_BUFSIZE  DUK_USE_DEBUG_BUFSIZE
10747 
10748 #if defined(DUK_USE_VARIADIC_MACROS)
10749 
duk_debug_log(duk_int_t level,const char * file,duk_int_t line,const char * func,const char * fmt,...)10750 DUK_INTERNAL void duk_debug_log(duk_int_t level, const char *file, duk_int_t line, const char *func, const char *fmt, ...) {
10751 	va_list ap;
10752 	long arg_level;
10753 	const char *arg_file;
10754 	long arg_line;
10755 	const char *arg_func;
10756 	const char *arg_msg;
10757 	char buf[DUK__DEBUG_BUFSIZE];
10758 
10759 	va_start(ap, fmt);
10760 
10761 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10762 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10763 
10764 	arg_level = (long) level;
10765 	arg_file = (const char *) file;
10766 	arg_line = (long) line;
10767 	arg_func = (const char *) func;
10768 	arg_msg = (const char *) buf;
10769 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10770 
10771 	va_end(ap);
10772 }
10773 
10774 #else  /* DUK_USE_VARIADIC_MACROS */
10775 
10776 DUK_INTERNAL char duk_debug_file_stash[DUK_DEBUG_STASH_SIZE];
10777 DUK_INTERNAL duk_int_t duk_debug_line_stash;
10778 DUK_INTERNAL char duk_debug_func_stash[DUK_DEBUG_STASH_SIZE];
10779 DUK_INTERNAL duk_int_t duk_debug_level_stash;
10780 
duk_debug_log(const char * fmt,...)10781 DUK_INTERNAL void duk_debug_log(const char *fmt, ...) {
10782 	va_list ap;
10783 	long arg_level;
10784 	const char *arg_file;
10785 	long arg_line;
10786 	const char *arg_func;
10787 	const char *arg_msg;
10788 	char buf[DUK__DEBUG_BUFSIZE];
10789 
10790 	va_start(ap, fmt);
10791 
10792 	duk_memzero((void *) buf, (size_t) DUK__DEBUG_BUFSIZE);
10793 	duk_debug_vsnprintf(buf, DUK__DEBUG_BUFSIZE - 1, fmt, ap);
10794 
10795 	arg_level = (long) duk_debug_level_stash;
10796 	arg_file = (const char *) duk_debug_file_stash;
10797 	arg_line = (long) duk_debug_line_stash;
10798 	arg_func = (const char *) duk_debug_func_stash;
10799 	arg_msg = (const char *) buf;
10800 	DUK_USE_DEBUG_WRITE(arg_level, arg_file, arg_line, arg_func, arg_msg);
10801 
10802 	va_end(ap);
10803 }
10804 
10805 #endif  /* DUK_USE_VARIADIC_MACROS */
10806 
10807 #else  /* DUK_USE_DEBUG */
10808 
10809 /*
10810  *  Debugging disabled
10811  */
10812 
10813 #endif  /* DUK_USE_DEBUG */
10814 
10815 /* automatic undefs */
10816 #undef DUK__DEBUG_BUFSIZE
10817 #line 1 "duk_builtins.c"
10818 /*
10819  *  Automatically generated by genbuiltins.py, do not edit!
10820  */
10821 
10822 /* #include duk_internal.h -> already included */
10823 
10824 #if defined(DUK_USE_ASSERTIONS)
10825 #define DUK__REFCINIT(refc) 0 /*h_assert_refcount*/, (refc) /*actual*/
10826 #else
10827 #define DUK__REFCINIT(refc) (refc) /*actual*/
10828 #endif
10829 
10830 #if defined(DUK_USE_ROM_STRINGS)
10831 #error ROM support not enabled, rerun configure.py with --rom-support
10832 #else  /* DUK_USE_ROM_STRINGS */
10833 DUK_INTERNAL const duk_uint8_t duk_strings_data[967] = {
10834 79,40,209,144,168,105,6,78,54,139,89,185,44,48,46,90,120,8,154,140,35,103,
10835 35,113,193,73,5,52,112,180,104,166,135,52,188,4,98,12,27,146,156,80,211,31,
10836 129,115,150,64,52,220,109,24,18,68,156,24,38,67,114,36,55,9,119,151,132,
10837 140,93,18,113,128,153,201,212,201,205,2,248,8,196,24,224,104,82,146,40,224,
10838 193,48,114,168,37,147,196,54,123,28,4,98,12,43,148,67,103,177,192,70,32,
10839 196,121,68,54,123,28,18,192,199,144,124,4,98,12,43,136,108,244,117,184,8,
10840 196,24,95,40,134,207,71,91,128,140,65,133,113,13,158,158,151,1,24,131,11,
10841 229,16,217,233,233,112,17,136,48,206,21,110,4,244,244,184,8,196,24,103,10,
10842 183,2,122,218,156,4,98,12,24,203,112,64,179,113,193,79,8,218,155,131,32,
10843 184,70,212,220,13,10,82,68,252,123,144,217,146,38,228,207,18,0,100,37,64,
10844 178,212,11,161,17,104,162,96,10,200,193,57,165,65,169,16,5,100,81,27,70,18,
10845 32,10,200,68,185,13,116,221,197,184,64,89,57,41,197,13,49,234,5,208,156,
10846 113,87,55,118,147,20,187,56,161,166,92,221,212,73,210,236,226,134,153,115,
10847 119,76,201,203,179,138,26,99,73,212,136,136,164,25,174,137,56,32,72,137,
10848 101,23,52,45,13,34,86,9,79,136,104,201,114,149,96,52,138,134,140,151,75,
10849 226,233,186,120,121,22,39,54,83,141,5,55,68,236,36,164,3,16,225,115,150,64,
10850 52,205,163,2,72,154,83,138,26,99,75,12,11,150,103,5,36,20,211,70,140,133,
10851 67,72,49,241,160,227,81,196,52,168,106,39,132,252,183,136,105,80,212,79,2,
10852 249,110,128,126,88,95,133,109,237,237,237,151,235,127,46,249,119,203,190,
10853 186,206,33,181,2,208,61,190,12,19,34,65,19,81,132,108,228,97,1,107,33,12,
10854 32,45,100,137,64,247,175,9,19,155,41,198,130,155,134,69,146,100,227,226,
10855 231,146,51,192,204,73,140,224,145,221,102,241,68,196,169,248,30,75,12,11,
10856 151,242,233,187,143,138,24,137,162,164,255,253,63,3,201,97,129,114,254,92,
10857 112,75,136,108,166,6,136,159,255,167,224,121,44,48,46,95,203,166,238,74,
10858 113,67,77,201,128,223,255,223,224,121,44,48,46,95,203,145,46,9,205,16,39,
10859 201,62,36,0,192,21,147,255,238,145,39,199,197,211,116,240,242,113,197,78,
10860 214,211,226,233,187,107,105,19,119,37,56,161,166,52,221,212,201,205,36,240,
10861 242,16,96,152,12,178,52,211,56,228,73,150,83,0,148,39,137,75,67,73,198,209,
10862 129,36,85,185,201,196,2,32,193,48,17,160,97,16,84,44,156,104,24,67,189,200,
10863 108,201,19,238,114,96,137,137,50,238,113,164,188,211,185,192,226,100,19,
10864 134,68,110,112,174,139,0,185,31,115,149,4,88,7,159,115,146,117,34,34,35,
10865 115,143,22,146,208,210,19,115,140,3,207,185,202,130,36,109,85,185,194,161,
10866 160,90,50,72,155,115,149,2,232,67,137,204,122,22,66,161,175,164,210,72,199,
10867 130,137,1,50,32,145,143,38,120,186,195,35,106,51,146,230,8,36,77,109,65,38,
10868 226,72,159,191,189,181,70,140,133,222,249,212,227,66,125,245,187,251,219,
10869 77,3,119,190,117,56,208,159,125,110,254,246,210,26,93,239,157,78,52,39,223,
10870 93,191,189,180,212,52,187,223,58,156,104,79,190,187,127,123,104,180,104,
10871 183,190,117,56,208,159,125,102,254,209,104,209,124,234,113,161,62,250,80,
10872 196,128,81,4,9,16,162,4,196,116,9,205,154,27,66,32,100,13,12,98,68,227,33,
10873 65,69,204,195,34,201,50,8,110,33,23,34,28,168,104,22,188,12,174,138,11,70,
10874 138,104,115,68,130,137,13,82,27,41,129,162,35,138,54,146,198,137,39,72,180,
10875 210,178,38,35,146,103,68,139,51,197,214,28,227,131,79,15,35,138,58,130,37,
10876 19,155,41,146,174,64,203,99,161,100,37,145,51,148,75,4,164,66,54,140,49,46,
10877 247,70,103,37,230,70,142,70,67,30,232,204,178,163,201,18,54,139,89,39,26,
10878 16,165,2,228,69,33,143,89,24,70,206,73,67,102,72,148,2,32,214,73,157,224,
10879 18,128,98,29,241,69,65,50,37,241,116,200,41,144,102,125,2,180,8,210,152,38,
10880 129,23,8,34,198,
10881 };
10882 #endif  /* DUK_USE_ROM_STRINGS */
10883 
10884 #if defined(DUK_USE_ROM_OBJECTS)
10885 #error ROM support not enabled, rerun configure.py with --rom-support
10886 #else  /* DUK_USE_ROM_OBJECTS */
10887 /* native functions: 177 */
10888 DUK_INTERNAL const duk_c_function duk_bi_native_functions[177] = {
10889 	NULL,
10890 	duk_bi_array_constructor,
10891 	duk_bi_array_constructor_is_array,
10892 	duk_bi_array_prototype_concat,
10893 	duk_bi_array_prototype_indexof_shared,
10894 	duk_bi_array_prototype_iter_shared,
10895 	duk_bi_array_prototype_join_shared,
10896 	duk_bi_array_prototype_pop,
10897 	duk_bi_array_prototype_push,
10898 	duk_bi_array_prototype_reduce_shared,
10899 	duk_bi_array_prototype_reverse,
10900 	duk_bi_array_prototype_shift,
10901 	duk_bi_array_prototype_slice,
10902 	duk_bi_array_prototype_sort,
10903 	duk_bi_array_prototype_splice,
10904 	duk_bi_array_prototype_to_string,
10905 	duk_bi_array_prototype_unshift,
10906 	duk_bi_arraybuffer_constructor,
10907 	duk_bi_arraybuffer_isview,
10908 	duk_bi_boolean_constructor,
10909 	duk_bi_boolean_prototype_tostring_shared,
10910 	duk_bi_buffer_compare_shared,
10911 	duk_bi_buffer_readfield,
10912 	duk_bi_buffer_slice_shared,
10913 	duk_bi_buffer_writefield,
10914 	duk_bi_dataview_constructor,
10915 	duk_bi_date_constructor,
10916 	duk_bi_date_constructor_now,
10917 	duk_bi_date_constructor_parse,
10918 	duk_bi_date_constructor_utc,
10919 	duk_bi_date_prototype_get_shared,
10920 	duk_bi_date_prototype_get_timezone_offset,
10921 	duk_bi_date_prototype_set_shared,
10922 	duk_bi_date_prototype_set_time,
10923 	duk_bi_date_prototype_to_json,
10924 	duk_bi_date_prototype_tostring_shared,
10925 	duk_bi_date_prototype_value_of,
10926 	duk_bi_duktape_object_act,
10927 	duk_bi_duktape_object_compact,
10928 	duk_bi_duktape_object_dec,
10929 	duk_bi_duktape_object_enc,
10930 	duk_bi_duktape_object_fin,
10931 	duk_bi_duktape_object_gc,
10932 	duk_bi_duktape_object_info,
10933 	duk_bi_error_constructor_shared,
10934 	duk_bi_error_prototype_filename_getter,
10935 	duk_bi_error_prototype_filename_setter,
10936 	duk_bi_error_prototype_linenumber_getter,
10937 	duk_bi_error_prototype_linenumber_setter,
10938 	duk_bi_error_prototype_stack_getter,
10939 	duk_bi_error_prototype_stack_setter,
10940 	duk_bi_error_prototype_to_string,
10941 	duk_bi_function_constructor,
10942 	duk_bi_function_prototype,
10943 	duk_bi_function_prototype_apply,
10944 	duk_bi_function_prototype_bind,
10945 	duk_bi_function_prototype_call,
10946 	duk_bi_function_prototype_to_string,
10947 	duk_bi_global_object_decode_uri,
10948 	duk_bi_global_object_decode_uri_component,
10949 	duk_bi_global_object_encode_uri,
10950 	duk_bi_global_object_encode_uri_component,
10951 	duk_bi_global_object_escape,
10952 	duk_bi_global_object_eval,
10953 	duk_bi_global_object_is_finite,
10954 	duk_bi_global_object_is_nan,
10955 	duk_bi_global_object_parse_float,
10956 	duk_bi_global_object_parse_int,
10957 	duk_bi_global_object_unescape,
10958 	duk_bi_json_object_parse,
10959 	duk_bi_json_object_stringify,
10960 	duk_bi_math_object_clz32,
10961 	duk_bi_math_object_hypot,
10962 	duk_bi_math_object_imul,
10963 	duk_bi_math_object_max,
10964 	duk_bi_math_object_min,
10965 	duk_bi_math_object_onearg_shared,
10966 	duk_bi_math_object_random,
10967 	duk_bi_math_object_sign,
10968 	duk_bi_math_object_twoarg_shared,
10969 	duk_bi_native_function_length,
10970 	duk_bi_native_function_name,
10971 	duk_bi_nodejs_buffer_byte_length,
10972 	duk_bi_nodejs_buffer_concat,
10973 	duk_bi_nodejs_buffer_constructor,
10974 	duk_bi_nodejs_buffer_copy,
10975 	duk_bi_nodejs_buffer_fill,
10976 	duk_bi_nodejs_buffer_is_buffer,
10977 	duk_bi_nodejs_buffer_is_encoding,
10978 	duk_bi_nodejs_buffer_tojson,
10979 	duk_bi_nodejs_buffer_tostring,
10980 	duk_bi_nodejs_buffer_write,
10981 	duk_bi_number_check_shared,
10982 	duk_bi_number_constructor,
10983 	duk_bi_number_prototype_to_exponential,
10984 	duk_bi_number_prototype_to_fixed,
10985 	duk_bi_number_prototype_to_locale_string,
10986 	duk_bi_number_prototype_to_precision,
10987 	duk_bi_number_prototype_to_string,
10988 	duk_bi_number_prototype_value_of,
10989 	duk_bi_object_constructor,
10990 	duk_bi_object_constructor_assign,
10991 	duk_bi_object_constructor_create,
10992 	duk_bi_object_constructor_define_properties,
10993 	duk_bi_object_constructor_define_property,
10994 	duk_bi_object_constructor_get_own_property_descriptor,
10995 	duk_bi_object_constructor_is,
10996 	duk_bi_object_constructor_is_extensible,
10997 	duk_bi_object_constructor_is_sealed_frozen_shared,
10998 	duk_bi_object_constructor_keys_shared,
10999 	duk_bi_object_constructor_prevent_extensions,
11000 	duk_bi_object_constructor_seal_freeze_shared,
11001 	duk_bi_object_getprototype_shared,
11002 	duk_bi_object_prototype_defineaccessor,
11003 	duk_bi_object_prototype_has_own_property,
11004 	duk_bi_object_prototype_is_prototype_of,
11005 	duk_bi_object_prototype_lookupaccessor,
11006 	duk_bi_object_prototype_property_is_enumerable,
11007 	duk_bi_object_prototype_to_locale_string,
11008 	duk_bi_object_prototype_to_string,
11009 	duk_bi_object_prototype_value_of,
11010 	duk_bi_object_setprototype_shared,
11011 	duk_bi_performance_now,
11012 	duk_bi_pointer_constructor,
11013 	duk_bi_pointer_prototype_tostring_shared,
11014 	duk_bi_proxy_constructor,
11015 	duk_bi_reflect_apply,
11016 	duk_bi_reflect_construct,
11017 	duk_bi_reflect_object_delete_property,
11018 	duk_bi_reflect_object_get,
11019 	duk_bi_reflect_object_has,
11020 	duk_bi_reflect_object_set,
11021 	duk_bi_regexp_constructor,
11022 	duk_bi_regexp_prototype_exec,
11023 	duk_bi_regexp_prototype_flags,
11024 	duk_bi_regexp_prototype_shared_getter,
11025 	duk_bi_regexp_prototype_test,
11026 	duk_bi_regexp_prototype_tostring,
11027 	duk_bi_string_constructor,
11028 	duk_bi_string_constructor_from_char_code,
11029 	duk_bi_string_constructor_from_code_point,
11030 	duk_bi_string_prototype_caseconv_shared,
11031 	duk_bi_string_prototype_char_at,
11032 	duk_bi_string_prototype_char_code_at,
11033 	duk_bi_string_prototype_concat,
11034 	duk_bi_string_prototype_includes,
11035 	duk_bi_string_prototype_indexof_shared,
11036 	duk_bi_string_prototype_locale_compare,
11037 	duk_bi_string_prototype_match,
11038 	duk_bi_string_prototype_repeat,
11039 	duk_bi_string_prototype_replace,
11040 	duk_bi_string_prototype_search,
11041 	duk_bi_string_prototype_slice,
11042 	duk_bi_string_prototype_split,
11043 	duk_bi_string_prototype_startswith_endswith,
11044 	duk_bi_string_prototype_substr,
11045 	duk_bi_string_prototype_substring,
11046 	duk_bi_string_prototype_to_string,
11047 	duk_bi_string_prototype_trim,
11048 	duk_bi_textdecoder_constructor,
11049 	duk_bi_textdecoder_prototype_decode,
11050 	duk_bi_textdecoder_prototype_shared_getter,
11051 	duk_bi_textencoder_constructor,
11052 	duk_bi_textencoder_prototype_encode,
11053 	duk_bi_textencoder_prototype_encoding_getter,
11054 	duk_bi_thread_constructor,
11055 	duk_bi_thread_current,
11056 	duk_bi_thread_resume,
11057 	duk_bi_thread_yield,
11058 	duk_bi_type_error_thrower,
11059 	duk_bi_typedarray_buffer_getter,
11060 	duk_bi_typedarray_bytelength_getter,
11061 	duk_bi_typedarray_byteoffset_getter,
11062 	duk_bi_typedarray_constructor,
11063 	duk_bi_typedarray_set,
11064 	duk_bi_uint8array_allocplain,
11065 	duk_bi_uint8array_plainof,
11066 };
11067 #if defined(DUK_USE_DOUBLE_LE)
11068 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11069 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11070 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11071 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11072 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11073 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11074 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11075 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11076 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11077 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11078 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11079 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11080 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11081 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11082 136,67,134,19,49,0,0,0,0,0,0,3,225,255,51,0,0,0,0,0,0,3,193,255,47,18,1,
11083 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11084 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11085 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11086 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11087 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11088 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11089 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11090 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11091 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11092 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11093 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11094 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11095 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11096 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11097 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11098 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11099 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11100 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11101 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11102 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11103 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11104 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11105 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11106 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11107 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11108 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11109 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11110 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11111 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11112 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11113 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11114 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11115 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11116 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11117 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11118 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11119 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11120 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11121 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11122 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11123 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11124 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11125 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11126 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11127 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11128 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11129 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,255,255,255,
11130 255,222,254,39,172,67,118,170,5,208,144,0,64,0,0,0,0,0,0,51,16,0,0,0,0,0,0,
11131 62,31,200,245,238,146,38,138,147,105,13,42,26,137,226,0,0,0,0,0,0,7,131,
11132 249,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,0,0,0,0,240,255,15,210,
11133 62,72,91,155,0,0,0,0,0,0,2,192,240,135,88,11,237,72,5,38,210,27,50,24,145,
11134 129,255,255,255,255,255,254,126,134,67,172,67,118,164,2,147,105,13,153,12,
11135 72,192,255,255,255,255,255,255,63,195,16,240,70,68,226,27,51,199,138,120,
11136 35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
11137 144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
11138 142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
11139 224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
11140 92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
11141 210,98,177,252,3,107,173,88,3,146,211,141,32,0,0,0,0,0,3,225,255,19,175,
11142 188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
11143 161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
11144 18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
11145 8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
11146 32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
11147 57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11148 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11149 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11150 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11151 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11152 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11153 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11154 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11155 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11156 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11157 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11158 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11159 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11160 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11161 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11162 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11163 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11164 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11165 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11166 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11167 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11168 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11169 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11170 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11171 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11172 28,24,61,73,25,33,205,128,0,0,0,0,1,167,166,129,108,242,151,15,39,8,34,26,
11173 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11174 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11175 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11176 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11177 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11178 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11179 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11180 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11181 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11182 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11183 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11184 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11185 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11186 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11187 196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,168,71,
11188 161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,200,
11189 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,7,129,249,155,51,
11190 232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,
11191 8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,2,1,155,52,40,
11192 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,72,
11193 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,52,
11194 104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,0,130,1,155,
11195 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,0,0,0,1,2,1,135,
11196 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11197 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11198 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11199 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11200 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11201 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11202 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11203 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11204 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11205 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11206 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11207 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11208 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11209 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11210 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11211 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11212 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11213 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11214 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11215 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11216 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11217 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11218 162,137,147,111,2,8,4,16,7,8,96,120,72,13,42,226,145,97,87,224,168,1,58,
11219 182,232,232,64,22,85,181,187,177,107,2,64,7,213,183,74,7,121,207,215,242,
11220 17,119,49,248,94,173,198,210,36,15,232,34,182,84,113,95,115,240,221,91,141,
11221 163,160,72,1,220,164,194,175,121,123,103,224,186,244,64,24,45,68,84,251,33,
11222 9,64,15,217,66,51,209,218,210,129,154,118,254,205,61,65,204,126,23,178,132,
11223 103,165,3,52,237,253,154,122,131,216,254,168,48,6,90,130,1,0,39,75,80,72,8,
11224 9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,
11225 65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,
11226 8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,
11227 168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,
11228 216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,
11229 234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,
11230 115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,
11231 76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,
11232 192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,
11233 182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,
11234 49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,
11235 39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,
11236 100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,
11237 217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,
11238 225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,
11239 156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
11240 114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
11241 69,145,132,108,224,0,0,0,0,0,0,120,31,153,172,56,132,122,28,76,146,218,121,
11242 35,180,69,145,132,108,224,0,0,0,0,0,0,120,31,168,160,45,110,23,30,176,33,
11243 184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,
11244 242,71,104,139,35,8,217,192,0,0,0,0,0,0,240,63,51,88,145,8,244,56,153,37,
11245 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,161,8,244,56,153,37,
11246 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,0,64,51,88,177,8,244,56,153,37,
11247 180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,193,8,244,56,153,
11248 37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,209,8,244,56,
11249 153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,16,64,51,88,225,8,244,
11250 56,153,37,180,242,71,104,139,35,8,217,192,0,0,0,0,0,0,32,64,32,227,194,0,
11251 97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
11252 29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
11253 112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
11254 240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
11255 148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
11256 214,3,192,
11257 };
11258 #elif defined(DUK_USE_DOUBLE_BE)
11259 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11260 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11261 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11262 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11263 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11264 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11265 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11266 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11267 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11268 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11269 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11270 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11271 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11272 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11273 136,67,134,19,49,1,255,224,0,0,0,0,0,3,51,1,255,192,0,0,0,0,0,3,47,18,1,
11274 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11275 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11276 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11277 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11278 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11279 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11280 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11281 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11282 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11283 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11284 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11285 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11286 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11287 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11288 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11289 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11290 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11291 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11292 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11293 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11294 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11295 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11296 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11297 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11298 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11299 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11300 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11301 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11302 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11303 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11304 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11305 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11306 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11307 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11308 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11309 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11310 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11311 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11312 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11313 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11314 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11315 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11316 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11317 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11318 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11319 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11320 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,128,255,223,255,255,255,
11321 255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,0,0,0,115,16,31,254,0,0,
11322 0,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,3,255,128,0,0,0,0,0,
11323 1,30,180,134,4,209,82,109,33,165,67,81,60,64,255,240,0,0,0,0,0,0,15,210,62,
11324 72,91,155,0,242,192,0,0,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,128,
11325 134,127,255,255,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,72,
11326 192,195,63,255,255,255,255,255,255,16,240,70,68,226,27,51,199,138,120,35,
11327 34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,144,
11328 196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,142,
11329 224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,224,
11330 3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,92,
11331 221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,210,
11332 98,177,252,3,107,173,88,3,146,211,141,33,255,224,0,0,0,0,0,3,19,175,188,0,
11333 100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,161,166,
11334 188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,18,155,
11335 184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,8,77,
11336 133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,32,
11337 35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,57,
11338 179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11339 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11340 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11341 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11342 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11343 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11344 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11345 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11346 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11347 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11348 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11349 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11350 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11351 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11352 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11353 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11354 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11355 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11356 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11357 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11358 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11359 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11360 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11361 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11362 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11363 28,24,61,73,25,33,205,128,129,167,166,0,0,0,0,1,108,242,151,15,39,8,34,26,
11364 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11365 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11366 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11367 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11368 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11369 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11370 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11371 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11372 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11373 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11374 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11375 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11376 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11377 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11378 196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,168,71,
11379 161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,200,
11380 71,161,196,201,45,167,146,59,68,89,24,70,206,1,255,128,0,0,0,0,0,1,155,51,
11381 232,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,
11382 8,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,0,0,0,0,0,0,1,155,52,40,
11383 71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,72,
11384 71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,52,
11385 104,71,161,196,201,45,167,146,59,68,89,24,70,206,2,0,128,0,0,0,0,0,1,155,
11386 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,2,1,0,0,0,0,0,0,1,135,
11387 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11388 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11389 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11390 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11391 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11392 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11393 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11394 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11395 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11396 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11397 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11398 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11399 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11400 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11401 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11402 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11403 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11404 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11405 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11406 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11407 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11408 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11409 162,137,147,111,2,8,4,16,7,8,96,120,72,8,0,183,225,81,98,138,237,33,58,182,
11410 232,232,64,64,2,107,177,187,181,85,22,7,213,183,74,1,255,49,114,23,247,209,
11411 207,120,94,173,198,210,36,3,255,113,84,118,82,184,47,224,221,91,141,163,
11412 160,72,7,251,121,111,98,164,220,161,192,186,244,64,64,9,33,251,84,68,45,24,
11413 15,217,66,51,209,218,210,128,127,205,65,60,204,254,119,154,23,178,132,103,
11414 165,0,255,218,130,121,153,252,239,54,168,48,6,90,130,1,0,39,75,80,72,8,9,
11415 33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,128,65,
11416 17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,234,10,8,
11417 41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,141,168,
11418 40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,47,0,216,
11419 134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,209,234,
11420 10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,192,115,3,
11421 117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,113,67,76,
11422 130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,1,78,192,
11423 56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,147,182,
11424 140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,188,24,49,
11425 39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,14,49,39,
11426 199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,35,100,
11427 128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,28,217,
11428 114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,32,225,
11429 64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,76,156,
11430 113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,114,1,
11431 18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,69,145,
11432 132,108,224,31,248,0,0,0,0,0,0,25,172,56,132,122,28,76,146,218,121,35,180,
11433 69,145,132,108,224,31,248,0,0,0,0,0,0,40,160,45,110,23,30,176,33,184,0,0,
11434 175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,180,242,71,
11435 104,139,35,8,217,192,63,240,0,0,0,0,0,0,51,88,145,8,244,56,153,37,180,242,
11436 71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,161,8,244,56,153,37,180,242,
11437 71,104,139,35,8,217,192,64,0,0,0,0,0,0,0,51,88,177,8,244,56,153,37,180,242,
11438 71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,193,8,244,56,153,37,180,
11439 242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,209,8,244,56,153,37,
11440 180,242,71,104,139,35,8,217,192,64,16,0,0,0,0,0,0,51,88,225,8,244,56,153,
11441 37,180,242,71,104,139,35,8,217,192,64,32,0,0,0,0,0,0,32,227,194,0,97,57,
11442 162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,29,153,
11443 1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,112,28,
11444 211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,240,117,
11445 32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,148,25,
11446 174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,214,3,
11447 192,
11448 };
11449 #elif defined(DUK_USE_DOUBLE_ME)
11450 DUK_INTERNAL const duk_uint8_t duk_builtins_data[4116] = {
11451 144,148,105,224,32,68,52,228,62,12,104,200,165,132,52,167,194,138,105,243,
11452 124,57,28,211,57,18,64,52,238,126,44,138,111,171,241,164,19,87,129,30,33,
11453 167,16,145,159,8,211,136,9,225,42,5,240,145,139,163,163,8,211,136,10,228,
11454 64,211,19,132,140,93,29,56,70,156,64,119,34,66,146,36,104,137,194,70,46,
11455 142,172,35,78,32,47,146,195,102,11,240,145,139,163,175,8,211,136,9,228,240,
11456 242,112,145,139,163,179,8,211,136,8,237,34,130,118,49,116,118,225,26,48,0,
11457 1,82,29,201,158,46,183,39,135,147,132,140,93,16,132,76,66,33,8,66,16,132,
11458 33,8,66,26,179,233,97,167,60,150,34,33,154,112,0,1,75,247,35,79,95,237,198,
11459 174,200,47,31,23,95,17,13,51,19,35,93,68,216,209,128,0,10,208,174,79,15,32,
11460 248,8,196,24,8,107,192,0,5,106,118,27,94,0,0,43,83,227,94,0,0,43,84,46,215,
11461 128,0,10,213,28,198,188,0,0,86,169,100,53,224,0,2,181,79,85,175,0,0,21,170,
11462 154,45,120,0,0,173,85,217,107,192,0,5,106,182,243,86,193,106,52,127,130,
11463 249,50,94,124,35,68,225,146,49,13,31,186,23,201,146,243,224,200,39,12,145,
11464 136,67,134,19,49,0,0,3,225,252,0,0,0,3,51,0,0,3,193,252,0,0,0,3,47,18,1,
11465 172,19,120,71,10,25,196,136,113,162,156,136,199,42,57,204,144,115,132,240,
11466 149,2,248,72,197,209,58,2,185,16,52,196,225,35,23,68,233,14,228,72,82,68,
11467 141,17,56,72,197,209,58,130,249,44,54,96,191,9,24,186,39,88,79,39,135,147,
11468 132,140,93,19,176,35,180,138,9,216,197,209,59,82,79,35,40,242,65,248,58,42,
11469 96,121,14,232,94,62,46,190,15,42,31,145,33,86,65,76,242,214,143,73,48,242,
11470 243,79,49,56,243,115,207,57,64,243,180,79,61,72,243,244,207,65,80,244,53,
11471 79,69,88,244,98,30,8,200,156,67,102,120,241,79,4,100,78,21,110,4,207,32,47,
11472 147,37,231,194,52,78,25,34,122,81,124,153,47,62,12,130,112,201,19,211,139,
11473 121,34,87,69,128,104,137,239,83,18,238,108,165,2,162,92,104,56,220,233,1,8,
11474 151,10,134,162,100,206,16,18,50,9,195,39,105,20,101,136,18,25,4,225,147,
11475 180,138,5,215,49,238,105,27,60,185,1,36,104,156,50,118,145,70,96,129,34,52,
11476 78,25,59,72,160,93,115,30,230,145,179,204,144,12,73,8,15,38,104,128,138,52,
11477 146,16,30,77,1,0,2,11,132,193,198,36,248,248,186,110,158,30,78,56,188,194,
11478 70,183,170,136,48,98,79,142,179,120,248,185,228,140,241,193,146,66,138,31,
11479 55,71,138,128,153,137,62,58,205,227,226,231,146,51,199,26,6,18,92,146,64,
11480 96,74,72,51,120,43,192,97,68,128,153,56,72,7,12,133,67,73,199,197,207,36,
11481 103,142,35,2,3,33,80,210,113,241,115,201,25,160,146,225,160,9,34,1,124,178,
11482 1,139,18,19,36,229,146,8,190,36,169,27,62,18,243,35,100,135,54,92,162,2,17,
11483 46,72,128,89,7,200,32,33,18,225,98,236,145,188,130,64,196,75,132,188,200,
11484 217,32,43,39,28,128,69,19,18,228,144,42,98,79,142,179,120,248,185,228,140,
11485 241,201,97,129,114,229,201,37,2,68,184,200,1,147,93,159,153,213,34,235,250,
11486 96,48,157,32,24,94,160,1,199,4,184,235,55,143,139,158,72,207,28,226,3,81,
11487 46,62,46,155,167,135,147,142,47,60,129,71,197,207,36,103,142,34,92,35,104,
11488 194,68,1,89,58,36,8,109,109,12,133,67,73,195,18,115,36,118,182,185,168,8,
11489 109,109,12,133,67,73,201,18,115,36,118,182,185,168,130,27,91,75,115,149,71,
11490 240,196,156,201,29,173,174,129,2,27,91,75,115,149,71,242,68,156,201,29,173,
11491 174,129,34,12,16,28,128,62,191,42,3,71,146,68,4,16,22,188,161,240,16,40,
11492 104,242,103,196,16,93,158,125,96,110,115,235,64,131,16,16,58,37,192,70,32,
11493 194,144,114,25,67,95,40,6,18,8,32,48,156,209,2,108,124,96,224,144,6,247,62,
11494 16,0,143,164,143,12,248,15,18,84,145,145,34,128,11,35,160,179,140,0,44,150,
11495 129,18,58,0,146,116,103,32,128,105,61,104,17,36,175,1,232,217,29,5,156,179,
11496 224,58,26,50,95,142,43,159,64,181,130,83,226,26,50,95,142,43,159,192,7,255,
11497 248,41,42,72,226,1,160,18,78,97,32,26,64,114,186,60,32,4,120,6,148,13,128,
11498 124,3,76,12,84,46,100,140,3,78,13,18,14,130,36,67,232,23,18,14,130,39,34,
11499 131,30,113,15,224,3,255,253,6,48,40,194,197,204,224,142,8,240,78,25,60,231,
11500 192,210,197,204,224,156,50,113,238,67,103,232,62,28,138,156,104,82,170,107,
11501 255,32,48,191,144,1,132,112,71,128,159,168,128,161,28,17,224,156,50,112,19,
11502 245,144,22,39,12,156,123,144,217,240,19,245,146,3,9,205,16,39,236,62,3,161,
11503 163,37,248,226,251,141,1,107,4,167,196,52,100,191,28,95,113,164,13,91,132,
11504 5,147,130,115,30,8,147,222,64,43,1,49,31,224,64,60,72,245,128,68,249,32,13,
11505 34,2,34,63,204,128,89,45,2,39,209,0,89,61,104,159,213,0,153,80,50,156,80,
11506 211,126,16,11,155,184,183,88,145,224,129,34,122,64,17,155,184,183,8,11,39,
11507 22,235,18,60,16,36,79,72,1,115,119,40,247,146,60,16,36,79,72,32,140,221,
11508 197,184,64,89,57,71,188,145,224,129,34,122,65,1,39,20,51,244,0,52,72,242,2,
11509 127,18,2,165,48,70,114,229,145,51,253,141,1,4,104,229,203,34,103,251,26,64,
11510 132,52,75,160,201,47,105,160,26,84,12,167,31,186,8,50,0,114,58,113,163,46,
11511 190,120,35,11,60,4,25,68,81,61,96,47,181,80,46,132,129,255,255,222,255,255,
11512 255,255,254,39,172,67,118,170,5,208,144,0,0,0,0,0,64,0,0,51,16,0,0,62,31,
11513 192,0,0,0,8,245,238,146,38,138,147,105,13,42,26,137,226,0,0,7,131,248,0,0,
11514 0,1,30,180,134,4,209,82,109,33,165,67,81,60,64,0,0,240,255,0,0,0,0,15,210,
11515 62,72,91,155,0,0,2,192,240,0,0,0,0,135,88,11,237,72,5,38,210,27,50,24,145,
11516 129,255,254,126,135,255,255,255,254,67,172,67,118,164,2,147,105,13,153,12,
11517 72,192,255,255,63,195,255,255,255,255,16,240,70,68,226,27,51,199,138,120,
11518 35,34,112,171,112,38,121,7,16,137,112,168,106,38,77,193,1,40,151,16,217,
11519 144,196,142,224,144,21,18,227,65,198,238,9,67,81,46,72,5,39,16,217,144,196,
11520 142,224,152,228,148,227,64,0,0,0,0,0,0,0,0,131,175,223,16,194,111,8,97,119,
11521 224,3,205,220,42,46,65,238,200,13,155,184,75,189,205,35,102,128,47,116,64,
11522 92,221,199,196,130,68,144,230,239,72,65,152,12,21,224,140,137,92,128,62,
11523 210,98,177,252,3,107,173,88,3,146,211,141,32,0,3,225,252,0,0,0,3,19,175,
11524 188,0,100,221,193,130,100,228,167,20,52,215,129,3,38,238,77,12,39,37,56,
11525 161,166,188,10,194,94,6,18,155,184,183,8,11,39,6,9,147,146,156,80,211,94,7,
11526 18,155,184,183,8,11,39,38,134,19,146,156,80,211,94,8,12,53,224,130,195,222,
11527 8,77,133,210,24,91,224,3,152,147,228,208,194,95,0,44,196,159,11,69,175,152,
11528 32,35,100,33,135,24,147,237,38,34,246,139,95,48,64,70,200,68,8,49,39,198,
11529 57,179,61,144,138,22,98,79,180,152,153,215,54,103,178,17,129,204,73,240,96,
11530 153,44,132,112,163,18,125,164,196,62,130,100,178,18,1,140,73,240,96,197,
11531 144,146,18,98,79,180,152,135,208,98,200,74,8,49,39,195,186,145,149,144,150,
11532 22,98,79,180,152,143,215,82,50,178,19,2,140,73,241,136,109,38,73,89,9,161,
11533 166,36,251,73,137,157,67,105,50,74,200,78,10,49,39,201,16,78,104,229,100,
11534 39,134,152,147,237,38,41,116,130,115,71,43,33,64,60,196,159,24,133,173,18,
11535 32,156,209,202,200,81,18,49,39,218,76,76,234,22,180,72,130,115,71,43,33,72,
11536 68,196,159,38,134,19,46,105,56,226,150,68,157,160,1,228,73,242,104,97,46,
11537 16,31,34,79,140,66,214,137,16,78,104,229,108,169,137,72,147,237,38,38,117,
11538 11,90,36,65,57,163,149,178,168,21,34,79,146,32,156,209,202,218,250,161,178,
11539 36,251,73,138,93,32,156,209,202,218,250,193,82,36,248,196,54,147,36,173,
11540 191,174,27,34,79,180,152,153,212,54,147,36,173,191,176,17,34,79,135,117,35,
11541 43,115,236,133,200,147,237,38,35,245,212,140,173,207,180,15,34,79,131,4,
11542 201,108,173,133,72,147,237,38,33,244,19,37,178,184,17,34,79,140,115,102,
11543 123,107,238,133,200,147,237,38,38,117,205,153,237,175,188,23,34,79,133,162,
11544 215,204,16,17,182,254,248,116,137,62,210,98,47,104,181,243,4,4,109,191,192,
11545 131,152,147,230,8,8,217,12,16,60,137,62,96,128,141,178,193,160,206,1,201,
11546 176,113,146,0,0,0,0,0,0,0,0,49,185,252,65,137,207,227,37,215,207,227,12,86,
11547 127,24,152,188,254,49,88,33,46,65,120,72,4,153,37,63,33,13,127,148,4,26,0,
11548 57,62,6,228,163,228,74,86,215,62,55,28,110,179,226,113,70,223,62,47,24,38,
11549 191,30,2,125,32,40,20,87,114,41,225,42,5,240,145,139,163,145,41,68,250,128,
11550 80,41,174,228,85,200,129,166,39,9,24,186,57,18,148,79,172,5,2,170,238,69,
11551 220,137,10,72,145,162,39,9,24,186,57,18,148,79,176,5,2,186,238,69,124,150,
11552 27,48,95,132,140,93,28,137,74,39,218,2,129,101,119,34,158,79,15,39,9,24,
11553 186,57,18,148,79,184,5,2,218,238,69,29,164,80,78,198,46,142,68,165,16,64,
11554 28,24,61,73,25,33,205,128,1,167,166,128,0,0,0,1,108,242,151,15,39,8,34,26,
11555 87,97,200,3,0,167,129,32,8,194,195,16,6,84,55,10,60,3,35,69,132,30,1,140,
11556 130,193,143,1,196,230,60,2,158,8,131,153,64,115,42,46,191,176,8,194,246,0,
11557 80,5,220,193,95,6,234,5,100,225,35,23,71,35,6,228,140,93,29,180,55,108,145,
11558 139,163,182,112,52,107,67,76,56,3,153,132,20,28,76,156,89,26,105,158,62,0,
11559 0,42,193,2,201,104,17,41,34,156,204,176,160,226,100,226,200,211,76,241,240,
11560 0,1,86,2,131,137,147,142,41,100,73,199,192,0,5,96,6,13,10,82,70,62,0,0,42,
11561 130,88,115,18,124,67,103,177,69,49,129,6,36,249,68,54,123,20,82,216,65,137,
11562 62,33,179,209,214,162,152,208,147,18,124,162,27,61,29,106,41,112,32,196,
11563 159,16,217,233,233,81,76,112,73,137,62,81,13,158,158,149,20,186,20,98,79,
11564 133,91,129,61,61,42,41,120,40,196,159,10,183,2,122,218,148,82,248,60,137,
11565 62,33,179,216,166,216,192,137,18,124,162,27,61,138,109,108,34,68,159,16,
11566 217,232,235,83,108,104,76,137,62,81,13,158,142,181,54,184,17,34,79,136,108,
11567 244,244,169,182,56,38,68,159,40,134,207,79,74,155,93,10,145,39,194,173,192,
11568 158,158,149,54,188,21,34,79,133,91,129,61,109,74,109,125,155,51,136,71,161,
11569 196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,168,71,
11570 161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,200,
11571 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,7,129,248,0,0,0,1,155,51,
11572 232,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,
11573 8,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,2,0,0,0,0,1,155,52,40,
11574 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,72,
11575 71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,52,
11576 104,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,0,130,0,0,0,0,1,155,
11577 52,136,71,161,196,201,45,167,146,59,68,89,24,70,206,0,0,1,2,0,0,0,0,1,135,
11578 52,166,32,76,72,1,246,136,235,103,177,69,0,136,144,3,226,27,61,138,41,44,
11579 50,36,0,251,68,117,179,209,214,234,201,69,16,50,36,0,251,68,117,179,209,
11580 214,232,73,69,34,5,196,128,31,16,217,232,235,117,100,162,147,2,226,64,15,
11581 136,108,244,117,186,18,81,74,129,145,32,7,218,35,173,158,158,151,86,74,40,
11582 161,145,32,7,218,35,173,158,158,151,66,74,41,20,46,36,0,248,134,207,79,75,
11583 171,37,20,154,23,18,0,124,67,103,167,165,208,146,138,85,11,137,0,62,21,110,
11584 4,250,178,81,70,11,137,0,62,21,110,4,250,18,81,72,193,145,32,7,193,186,129,
11585 89,58,178,81,71,12,137,0,62,13,212,10,201,208,146,138,71,10,137,0,62,209,
11586 29,108,250,178,81,104,1,81,32,7,218,35,173,159,66,74,45,32,38,36,0,248,134,
11587 207,171,37,22,160,19,18,0,124,67,103,208,146,139,88,10,180,81,50,118,136,
11588 235,103,177,77,128,155,69,19,39,16,217,236,83,105,97,182,138,38,78,209,29,
11589 108,244,117,186,178,83,100,13,180,81,50,118,136,235,103,163,173,208,146,
11590 155,68,12,180,81,50,113,13,158,142,183,86,74,109,48,50,209,68,201,196,54,
11591 122,58,221,9,41,181,64,219,69,19,39,104,142,182,122,122,93,89,41,178,134,
11592 218,40,153,59,68,117,179,211,210,232,73,77,162,134,90,40,153,56,134,207,79,
11593 75,171,37,54,154,25,104,162,100,226,27,61,61,46,132,148,218,168,101,162,
11594 137,147,133,91,129,62,172,148,217,131,45,20,76,156,42,220,9,244,36,166,209,
11595 131,109,20,76,156,27,168,21,147,171,37,54,112,219,69,19,39,6,234,5,100,232,
11596 73,77,163,133,218,40,153,59,68,117,179,234,201,78,32,5,218,40,153,59,68,
11597 117,179,232,73,78,36,5,90,40,153,56,134,207,171,37,56,160,21,104,162,100,
11598 226,27,62,132,148,226,195,95,182,97,176,218,128,8,84,45,123,38,1,137,10,1,
11599 114,160,64,56,156,199,130,36,160,72,8,39,63,27,24,1,100,180,8,148,146,0,45,
11600 162,137,147,111,2,8,4,16,7,8,96,120,72,1,87,224,168,13,42,226,145,97,58,
11601 182,232,232,64,177,107,2,64,22,85,181,187,7,213,183,74,2,17,119,49,255,121,
11602 207,215,240,94,173,198,210,36,4,113,95,115,255,232,34,182,80,221,91,141,
11603 163,160,72,15,121,123,103,225,220,164,194,160,186,244,64,251,33,9,64,24,45,
11604 68,84,15,217,66,51,209,218,210,129,61,65,204,127,154,118,254,204,23,178,
11605 132,103,165,2,122,131,216,255,52,237,253,154,168,48,6,90,130,1,0,39,75,80,
11606 72,8,9,33,186,130,80,64,76,13,212,19,2,130,96,110,150,173,0,65,6,51,212,20,
11607 128,65,17,11,212,19,130,137,121,211,210,209,144,6,39,75,80,80,0,201,119,
11608 234,10,8,41,86,231,71,80,80,129,79,135,186,122,69,224,34,25,69,233,80,3,91,
11609 141,168,40,96,139,113,180,181,5,36,21,110,54,142,134,160,165,1,176,23,211,
11610 47,0,216,134,233,215,128,111,117,181,104,128,209,3,70,230,106,64,5,139,168,
11611 209,234,10,32,36,144,102,234,136,3,146,27,168,40,160,146,132,103,168,40,
11612 192,115,3,117,5,28,22,113,163,69,168,41,103,1,66,188,17,145,52,40,4,202,
11613 113,67,76,130,227,68,194,13,240,108,0,0,83,96,0,2,161,0,104,146,84,97,48,0,
11614 1,78,192,56,169,24,145,179,192,0,5,48,8,56,16,32,128,56,18,52,125,166,86,
11615 147,182,140,28,50,21,13,39,31,23,60,145,158,56,140,141,47,113,6,155,186,
11616 188,24,49,39,199,89,188,124,92,242,70,120,224,201,33,69,15,155,163,197,68,
11617 14,49,39,199,197,211,116,240,242,113,197,230,18,180,253,228,3,17,46,18,243,
11618 35,100,128,172,156,114,70,163,146,76,34,248,146,164,108,248,75,204,141,146,
11619 28,217,114,137,27,78,251,241,173,234,162,160,225,1,3,34,92,170,9,105,164,
11620 32,225,64,131,155,1,193,133,7,19,39,22,70,154,103,143,128,0,10,176,20,28,
11621 76,156,113,75,34,78,62,0,0,43,0,48,104,82,146,49,240,0,1,84,11,180,192,0,5,
11622 114,1,18,160,65,24,131,20,145,25,172,48,132,122,28,76,146,218,121,35,180,
11623 69,145,132,108,224,0,0,120,31,128,0,0,0,25,172,56,132,122,28,76,146,218,
11624 121,35,180,69,145,132,108,224,0,0,120,31,128,0,0,0,40,160,45,110,23,30,176,
11625 33,184,0,0,175,32,29,235,2,27,199,23,0,0,22,4,51,88,129,8,244,56,153,37,
11626 180,242,71,104,139,35,8,217,192,0,0,240,63,0,0,0,0,51,88,145,8,244,56,153,
11627 37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,161,8,244,56,153,
11628 37,180,242,71,104,139,35,8,217,192,0,0,0,64,0,0,0,0,51,88,177,8,244,56,153,
11629 37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,193,8,244,56,
11630 153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,209,8,244,
11631 56,153,37,180,242,71,104,139,35,8,217,192,0,0,16,64,0,0,0,0,51,88,225,8,
11632 244,56,153,37,180,242,71,104,139,35,8,217,192,0,0,32,64,0,0,0,0,32,227,194,
11633 0,97,57,162,4,245,232,5,34,92,35,68,225,161,166,218,16,16,137,112,52,41,73,
11634 29,153,1,65,196,201,197,145,166,153,245,200,3,137,204,120,34,74,8,200,58,
11635 112,28,211,32,130,52,78,26,26,110,248,0,0,164,4,12,70,137,195,39,252,73,
11636 240,117,32,57,168,97,4,104,156,52,52,221,255,160,20,160,152,23,223,250,32,
11637 148,25,174,137,58,23,51,191,244,84,12,50,9,195,39,240,81,238,2,3,107,173,
11638 214,3,192,
11639 };
11640 #else
11641 #error invalid endianness defines
11642 #endif
11643 #endif  /* DUK_USE_ROM_OBJECTS */
11644 
11645 /* automatic undefs */
11646 #undef DUK__REFCINIT
11647 #line 1 "duk_error_macros.c"
11648 /*
11649  *  Error and fatal handling.
11650  */
11651 
11652 /* #include duk_internal.h -> already included */
11653 
11654 #define DUK__ERRFMT_BUFSIZE  256  /* size for formatting buffers */
11655 
11656 #if defined(DUK_USE_VERBOSE_ERRORS)
11657 
duk_err_handle_error_fmt(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * fmt,...)11658 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, ...) {
11659 	va_list ap;
11660 	char msg[DUK__ERRFMT_BUFSIZE];
11661 	va_start(ap, fmt);
11662 	(void) DUK_VSNPRINTF(msg, sizeof(msg), fmt, ap);
11663 	msg[sizeof(msg) - 1] = (char) 0;
11664 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11665 	va_end(ap);  /* dead code, but ensures portability (see Linux man page notes) */
11666 }
11667 
duk_err_handle_error(duk_hthread * thr,const char * filename,duk_uint_t line_and_code,const char * msg)11668 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, const char *filename, duk_uint_t line_and_code, const char *msg) {
11669 	duk_err_create_and_throw(thr, (duk_errcode_t) (line_and_code >> 24), msg, filename, (duk_int_t) (line_and_code & 0x00ffffffL));
11670 }
11671 
11672 #else  /* DUK_USE_VERBOSE_ERRORS */
11673 
duk_err_handle_error(duk_hthread * thr,duk_errcode_t code)11674 DUK_INTERNAL DUK_COLD void duk_err_handle_error(duk_hthread *thr, duk_errcode_t code) {
11675 	duk_err_create_and_throw(thr, code);
11676 }
11677 
11678 #endif  /* DUK_USE_VERBOSE_ERRORS */
11679 
11680 /*
11681  *  Error throwing helpers
11682  */
11683 
11684 #if defined(DUK_USE_VERBOSE_ERRORS)
11685 #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)11686 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) {
11687 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11688 	                   expect_name, duk_get_type_name(thr, idx), (long) idx);
11689 }
11690 #else
duk_err_require_type_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx,const char * expect_name)11691 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) {
11692 	DUK_ERROR_RAW_FMT3(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, "%s required, found %s (stack index %ld)",
11693 	                   expect_name, duk_push_string_readable(thr, idx), (long) idx);
11694 }
11695 #endif
duk_err_error_internal(duk_hthread * thr,const char * filename,duk_int_t linenumber)11696 DUK_INTERNAL DUK_COLD void duk_err_error_internal(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11697 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_INTERNAL_ERROR);
11698 }
duk_err_error_alloc_failed(duk_hthread * thr,const char * filename,duk_int_t linenumber)11699 DUK_INTERNAL DUK_COLD void duk_err_error_alloc_failed(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11700 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, DUK_STR_ALLOC_FAILED);
11701 }
duk_err_error(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11702 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11703 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_ERROR, message);
11704 }
duk_err_range(duk_hthread * thr,const char * filename,duk_int_t linenumber,const char * message)11705 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr, const char *filename, duk_int_t linenumber, const char *message) {
11706 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, message);
11707 }
duk_err_range_index(duk_hthread * thr,const char * filename,duk_int_t linenumber,duk_idx_t idx)11708 DUK_INTERNAL DUK_COLD void duk_err_range_index(duk_hthread *thr, const char *filename, duk_int_t linenumber, duk_idx_t idx) {
11709 	DUK_ERROR_RAW_FMT1(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, "invalid stack index %ld", (long) (idx));
11710 }
duk_err_range_push_beyond(duk_hthread * thr,const char * filename,duk_int_t linenumber)11711 DUK_INTERNAL DUK_COLD void duk_err_range_push_beyond(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11712 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_RANGE_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
11713 }
duk_err_type_invalid_args(duk_hthread * thr,const char * filename,duk_int_t linenumber)11714 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_args(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11715 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_ARGS);
11716 }
duk_err_type_invalid_state(duk_hthread * thr,const char * filename,duk_int_t linenumber)11717 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_state(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11718 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_STATE);
11719 }
duk_err_type_invalid_trap_result(duk_hthread * thr,const char * filename,duk_int_t linenumber)11720 DUK_INTERNAL DUK_COLD void duk_err_type_invalid_trap_result(duk_hthread *thr, const char *filename, duk_int_t linenumber) {
11721 	DUK_ERROR_RAW(thr, filename, linenumber, DUK_ERR_TYPE_ERROR, DUK_STR_INVALID_TRAP_RESULT);
11722 }
11723 #else
11724 /* The file/line arguments are NULL and 0, they're ignored by DUK_ERROR_RAW()
11725  * when non-verbose errors are used.
11726  */
11727 
11728 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)11729 DUK_LOCAL void duk__err_shared(duk_hthread *thr, duk_errcode_t code) {
11730 	DUK_ERROR_RAW(thr, NULL, 0, code, NULL);
11731 }
duk_err_error(duk_hthread * thr)11732 DUK_INTERNAL DUK_COLD void duk_err_error(duk_hthread *thr) {
11733 	duk__err_shared(thr, DUK_ERR_ERROR);
11734 }
duk_err_range(duk_hthread * thr)11735 DUK_INTERNAL DUK_COLD void duk_err_range(duk_hthread *thr) {
11736 	duk__err_shared(thr, DUK_ERR_RANGE_ERROR);
11737 }
duk_err_eval(duk_hthread * thr)11738 DUK_INTERNAL DUK_COLD void duk_err_eval(duk_hthread *thr) {
11739 	duk__err_shared(thr, DUK_ERR_EVAL_ERROR);
11740 }
duk_err_reference(duk_hthread * thr)11741 DUK_INTERNAL DUK_COLD void duk_err_reference(duk_hthread *thr) {
11742 	duk__err_shared(thr, DUK_ERR_REFERENCE_ERROR);
11743 }
duk_err_syntax(duk_hthread * thr)11744 DUK_INTERNAL DUK_COLD void duk_err_syntax(duk_hthread *thr) {
11745 	duk__err_shared(thr, DUK_ERR_SYNTAX_ERROR);
11746 }
duk_err_type(duk_hthread * thr)11747 DUK_INTERNAL DUK_COLD void duk_err_type(duk_hthread *thr) {
11748 	duk__err_shared(thr, DUK_ERR_TYPE_ERROR);
11749 }
duk_err_uri(duk_hthread * thr)11750 DUK_INTERNAL DUK_COLD void duk_err_uri(duk_hthread *thr) {
11751 	duk__err_shared(thr, DUK_ERR_URI_ERROR);
11752 }
11753 #endif
11754 
11755 /*
11756  *  Default fatal error handler
11757  */
11758 
duk_default_fatal_handler(void * udata,const char * msg)11759 DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *msg) {
11760 	DUK_UNREF(udata);
11761 	DUK_UNREF(msg);
11762 
11763 	msg = msg ? msg : "NULL";
11764 
11765 #if defined(DUK_USE_FATAL_HANDLER)
11766 	/* duk_config.h provided a custom default fatal handler. */
11767 	DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
11768 	DUK_USE_FATAL_HANDLER(udata, msg);
11769 #elif defined(DUK_USE_CPP_EXCEPTIONS)
11770 	/* With C++ use a duk_fatal_exception which user code can catch in
11771 	 * a natural way.
11772 	 */
11773 	DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
11774 	throw duk_fatal_exception(msg);
11775 #else
11776 	/* Default behavior is to abort() on error.  There's no printout
11777 	 * which makes this awkward, so it's always recommended to use an
11778 	 * explicit fatal error handler.
11779 	 *
11780 	 * ====================================================================
11781 	 * NOTE: If you are seeing this, you are most likely dealing with an
11782 	 * uncaught error.  You should provide a fatal error handler in Duktape
11783 	 * heap creation, and should consider using a protected call as your
11784 	 * first call into an empty Duktape context to properly handle errors.
11785 	 * See:
11786 	 *   - http://duktape.org/guide.html#error-handling
11787 	 *   - http://wiki.duktape.org/HowtoFatalErrors.html
11788 	 *   - http://duktape.org/api.html#taglist-protected
11789 	 * ====================================================================
11790 	 */
11791 	DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
11792 	DUK_ABORT();
11793 #endif
11794 
11795 	DUK_D(DUK_DPRINT("fatal error handler returned, enter forever loop"));
11796 	for (;;) {
11797 		/* Loop forever to ensure we don't return. */
11798 	}
11799 }
11800 
11801 /* automatic undefs */
11802 #undef DUK__ERRFMT_BUFSIZE
11803 #line 1 "duk_unicode_support.c"
11804 /*
11805  *  Various Unicode help functions for character classification predicates,
11806  *  case conversion, decoding, etc.
11807  */
11808 
11809 /* #include duk_internal.h -> already included */
11810 
11811 /*
11812  *  Fast path tables
11813  */
11814 
11815 #if defined(DUK_USE_IDCHAR_FASTPATH)
11816 DUK_INTERNAL const duk_int8_t duk_is_idchar_tab[128] = {
11817 	/* 0: not IdentifierStart or IdentifierPart
11818 	 * 1: IdentifierStart and IdentifierPart
11819 	 * -1: IdentifierPart only
11820 	 */
11821 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x00...0x0f */
11822 	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x10...0x1f */
11823 	0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /* 0x20...0x2f */
11824 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,  0,  0,  0,  0,  0,   /* 0x30...0x3f */
11825 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x40...0x4f */
11826 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,   /* 0x50...0x5f */
11827 	0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,   /* 0x60...0x6f */
11828 	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0    /* 0x70...0x7f */
11829 };
11830 #endif
11831 
11832 /*
11833  *  XUTF-8 and CESU-8 encoding/decoding
11834  */
11835 
duk_unicode_get_xutf8_length(duk_ucodepoint_t cp)11836 DUK_INTERNAL duk_small_int_t duk_unicode_get_xutf8_length(duk_ucodepoint_t cp) {
11837 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11838 	if (x < 0x80UL) {
11839 		/* 7 bits */
11840 		return 1;
11841 	} else if (x < 0x800UL) {
11842 		/* 11 bits */
11843 		return 2;
11844 	} else if (x < 0x10000UL) {
11845 		/* 16 bits */
11846 		return 3;
11847 	} else if (x < 0x200000UL) {
11848 		/* 21 bits */
11849 		return 4;
11850 	} else if (x < 0x4000000UL) {
11851 		/* 26 bits */
11852 		return 5;
11853 	} else if (x < (duk_ucodepoint_t) 0x80000000UL) {
11854 		/* 31 bits */
11855 		return 6;
11856 	} else {
11857 		/* 36 bits */
11858 		return 7;
11859 	}
11860 }
11861 
11862 #if defined(DUK_USE_ASSERTIONS)
duk_unicode_get_cesu8_length(duk_ucodepoint_t cp)11863 DUK_INTERNAL duk_small_int_t duk_unicode_get_cesu8_length(duk_ucodepoint_t cp) {
11864 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11865 	if (x < 0x80UL) {
11866 		/* 7 bits */
11867 		return 1;
11868 	} else if (x < 0x800UL) {
11869 		/* 11 bits */
11870 		return 2;
11871 	} else if (x < 0x10000UL) {
11872 		/* 16 bits */
11873 		return 3;
11874 	} else {
11875 		/* Encoded as surrogate pair, each encoding to 3 bytes for
11876 		 * 6 bytes total.  Codepoints above U+10FFFF encode as 6 bytes
11877 		 * too, see duk_unicode_encode_cesu8().
11878 		  */
11879 		return 3 + 3;
11880 	}
11881 }
11882 #endif  /* DUK_USE_ASSERTIONS */
11883 
11884 DUK_INTERNAL const duk_uint8_t duk_unicode_xutf8_markers[7] = {
11885 	0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
11886 };
11887 
11888 /* Encode to extended UTF-8; 'out' must have space for at least
11889  * DUK_UNICODE_MAX_XUTF8_LENGTH bytes.  Allows encoding of any
11890  * 32-bit (unsigned) codepoint.
11891  */
duk_unicode_encode_xutf8(duk_ucodepoint_t cp,duk_uint8_t * out)11892 DUK_INTERNAL duk_small_int_t duk_unicode_encode_xutf8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11893 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11894 	duk_small_int_t len;
11895 	duk_uint8_t marker;
11896 	duk_small_int_t i;
11897 
11898 	len = duk_unicode_get_xutf8_length(cp);
11899 	DUK_ASSERT(len > 0);
11900 
11901 	marker = duk_unicode_xutf8_markers[len - 1];  /* 64-bit OK because always >= 0 */
11902 
11903 	i = len;
11904 	DUK_ASSERT(i > 0);
11905 	do {
11906 		i--;
11907 		if (i > 0) {
11908 			out[i] = (duk_uint8_t) (0x80 + (x & 0x3f));
11909 			x >>= 6;
11910 		} else {
11911 			/* Note: masking of 'x' is not necessary because of
11912 			 * range check and shifting -> no bits overlapping
11913 			 * the marker should be set.
11914 			 */
11915 			out[0] = (duk_uint8_t) (marker + x);
11916 		}
11917 	} while (i > 0);
11918 
11919 	return len;
11920 }
11921 
11922 /* Encode to CESU-8; 'out' must have space for at least
11923  * DUK_UNICODE_MAX_CESU8_LENGTH bytes; codepoints above U+10FFFF
11924  * will encode to garbage but won't overwrite the output buffer.
11925  */
duk_unicode_encode_cesu8(duk_ucodepoint_t cp,duk_uint8_t * out)11926 DUK_INTERNAL duk_small_int_t duk_unicode_encode_cesu8(duk_ucodepoint_t cp, duk_uint8_t *out) {
11927 	duk_uint_fast32_t x = (duk_uint_fast32_t) cp;
11928 	duk_small_int_t len;
11929 
11930 	if (x < 0x80UL) {
11931 		out[0] = (duk_uint8_t) x;
11932 		len = 1;
11933 	} else if (x < 0x800UL) {
11934 		out[0] = (duk_uint8_t) (0xc0 + ((x >> 6) & 0x1f));
11935 		out[1] = (duk_uint8_t) (0x80 + (x & 0x3f));
11936 		len = 2;
11937 	} else if (x < 0x10000UL) {
11938 		/* surrogate pairs get encoded here */
11939 		out[0] = (duk_uint8_t) (0xe0 + ((x >> 12) & 0x0f));
11940 		out[1] = (duk_uint8_t) (0x80 + ((x >> 6) & 0x3f));
11941 		out[2] = (duk_uint8_t) (0x80 + (x & 0x3f));
11942 		len = 3;
11943 	} else {
11944 		/*
11945 		 *  Unicode codepoints above U+FFFF are encoded as surrogate
11946 		 *  pairs here.  This ensures that all CESU-8 codepoints are
11947 		 *  16-bit values as expected in ECMAScript.  The surrogate
11948 		 *  pairs always get a 3-byte encoding (each) in CESU-8.
11949 		 *  See: http://en.wikipedia.org/wiki/Surrogate_pair
11950 		 *
11951 		 *  20-bit codepoint, 10 bits (A and B) per surrogate pair:
11952 		 *
11953 		 *    x = 0b00000000 0000AAAA AAAAAABB BBBBBBBB
11954 		 *  sp1 = 0b110110AA AAAAAAAA  (0xd800 + ((x >> 10) & 0x3ff))
11955 		 *  sp2 = 0b110111BB BBBBBBBB  (0xdc00 + (x & 0x3ff))
11956 		 *
11957 		 *  Encoded into CESU-8:
11958 		 *
11959 		 *  sp1 -> 0b11101101  (0xe0 + ((sp1 >> 12) & 0x0f))
11960 		 *      -> 0b1010AAAA  (0x80 + ((sp1 >> 6) & 0x3f))
11961 		 *      -> 0b10AAAAAA  (0x80 + (sp1 & 0x3f))
11962 		 *  sp2 -> 0b11101101  (0xe0 + ((sp2 >> 12) & 0x0f))
11963 		 *      -> 0b1011BBBB  (0x80 + ((sp2 >> 6) & 0x3f))
11964 		 *      -> 0b10BBBBBB  (0x80 + (sp2 & 0x3f))
11965 		 *
11966 		 *  Note that 0x10000 must be subtracted first.  The code below
11967 		 *  avoids the sp1, sp2 temporaries which saves around 20 bytes
11968 		 *  of code.
11969 		 */
11970 
11971 		x -= 0x10000UL;
11972 
11973 		out[0] = (duk_uint8_t) (0xed);
11974 		out[1] = (duk_uint8_t) (0xa0 + ((x >> 16) & 0x0f));
11975 		out[2] = (duk_uint8_t) (0x80 + ((x >> 10) & 0x3f));
11976 		out[3] = (duk_uint8_t) (0xed);
11977 		out[4] = (duk_uint8_t) (0xb0 + ((x >> 6) & 0x0f));
11978 		out[5] = (duk_uint8_t) (0x80 + (x & 0x3f));
11979 		len = 6;
11980 	}
11981 
11982 	return len;
11983 }
11984 
11985 /* 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)11986 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) {
11987 	const duk_uint8_t *p;
11988 	duk_uint32_t res;
11989 	duk_uint_fast8_t ch;
11990 	duk_small_int_t n;
11991 
11992 	DUK_UNREF(thr);
11993 
11994 	p = *ptr;
11995 	if (p < ptr_start || p >= ptr_end) {
11996 		goto fail;
11997 	}
11998 
11999 	/*
12000 	 *  UTF-8 decoder which accepts longer than standard byte sequences.
12001 	 *  This allows full 32-bit code points to be used.
12002 	 */
12003 
12004 	ch = (duk_uint_fast8_t) (*p++);
12005 	if (ch < 0x80) {
12006 		/* 0xxx xxxx   [7 bits] */
12007 		res = (duk_uint32_t) (ch & 0x7f);
12008 		n = 0;
12009 	} else if (ch < 0xc0) {
12010 		/* 10xx xxxx -> invalid */
12011 		goto fail;
12012 	} else if (ch < 0xe0) {
12013 		/* 110x xxxx   10xx xxxx   [11 bits] */
12014 		res = (duk_uint32_t) (ch & 0x1f);
12015 		n = 1;
12016 	} else if (ch < 0xf0) {
12017 		/* 1110 xxxx   10xx xxxx   10xx xxxx   [16 bits] */
12018 		res = (duk_uint32_t) (ch & 0x0f);
12019 		n = 2;
12020 	} else if (ch < 0xf8) {
12021 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx   [21 bits] */
12022 		res = (duk_uint32_t) (ch & 0x07);
12023 		n = 3;
12024 	} else if (ch < 0xfc) {
12025 		/* 1111 10xx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [26 bits] */
12026 		res = (duk_uint32_t) (ch & 0x03);
12027 		n = 4;
12028 	} else if (ch < 0xfe) {
12029 		/* 1111 110x   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [31 bits] */
12030 		res = (duk_uint32_t) (ch & 0x01);
12031 		n = 5;
12032 	} else if (ch < 0xff) {
12033 		/* 1111 1110   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [36 bits] */
12034 		res = (duk_uint32_t) (0);
12035 		n = 6;
12036 	} else {
12037 		/* 8-byte format could be:
12038 		 * 1111 1111   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   10xx xxxx   [41 bits]
12039 		 *
12040 		 * However, this format would not have a zero bit following the
12041 		 * leading one bits and would not allow 0xFF to be used as an
12042 		 * "invalid xutf-8" marker for internal keys.  Further, 8-byte
12043 		 * encodings (up to 41 bit code points) are not currently needed.
12044 		 */
12045 		goto fail;
12046 	}
12047 
12048 	DUK_ASSERT(p >= ptr_start);  /* verified at beginning */
12049 	if (p + n > ptr_end) {
12050 		/* check pointer at end */
12051 		goto fail;
12052 	}
12053 
12054 	while (n > 0) {
12055 		DUK_ASSERT(p >= ptr_start && p < ptr_end);
12056 		ch = (duk_uint_fast8_t) (*p++);
12057 #if 0
12058 		if (ch & 0xc0 != 0x80) {
12059 			/* not a continuation byte */
12060 			p--;
12061 			*ptr = p;
12062 			*out_cp = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
12063 			return 1;
12064 		}
12065 #endif
12066 		res = (res << 6) + (duk_uint32_t) (ch & 0x3f);
12067 		n--;
12068 	}
12069 
12070 	*ptr = p;
12071 	*out_cp = res;
12072 	return 1;
12073 
12074  fail:
12075 	return 0;
12076 }
12077 
12078 /* 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)12079 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) {
12080 	duk_ucodepoint_t cp;
12081 
12082 	if (duk_unicode_decode_xutf8(thr, ptr, ptr_start, ptr_end, &cp)) {
12083 		return cp;
12084 	}
12085 	DUK_ERROR_INTERNAL(thr);
12086 	DUK_WO_NORETURN(return 0;);
12087 }
12088 
12089 /* Compute (extended) utf-8 length without codepoint encoding validation,
12090  * used for string interning.
12091  *
12092  * NOTE: This algorithm is performance critical, more so than string hashing
12093  * in some cases.  It is needed when interning a string and needs to scan
12094  * every byte of the string with no skipping.  Having an ASCII fast path
12095  * is useful if possible in the algorithm.  The current algorithms were
12096  * chosen from several variants, based on x64 gcc -O2 testing.  See:
12097  * https://github.com/svaarala/duktape/pull/422
12098  *
12099  * NOTE: must match tools/dukutil.py:duk_unicode_unvalidated_utf8_length().
12100  */
12101 
12102 #if defined(DUK_USE_PREFER_SIZE)
12103 /* Small variant; roughly 150 bytes smaller than the fast variant. */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12104 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12105 	const duk_uint8_t *p;
12106 	const duk_uint8_t *p_end;
12107 	duk_size_t ncont;
12108 	duk_size_t clen;
12109 
12110 	p = data;
12111 	p_end = data + blen;
12112 	ncont = 0;
12113 	while (p != p_end) {
12114 		duk_uint8_t x;
12115 		x = *p++;
12116 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12117 			ncont++;
12118 		}
12119 	}
12120 
12121 	DUK_ASSERT(ncont <= blen);
12122 	clen = blen - ncont;
12123 	DUK_ASSERT(clen <= blen);
12124 	return clen;
12125 }
12126 #else  /* DUK_USE_PREFER_SIZE */
12127 /* This seems like a good overall approach.  Fast path for ASCII in 4 byte
12128  * blocks.
12129  */
duk_unicode_unvalidated_utf8_length(const duk_uint8_t * data,duk_size_t blen)12130 DUK_INTERNAL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen) {
12131 	const duk_uint8_t *p;
12132 	const duk_uint8_t *p_end;
12133 	const duk_uint32_t *p32_end;
12134 	const duk_uint32_t *p32;
12135 	duk_size_t ncont;
12136 	duk_size_t clen;
12137 
12138 	ncont = 0;  /* number of continuation (non-initial) bytes in [0x80,0xbf] */
12139 	p = data;
12140 	p_end = data + blen;
12141 	if (blen < 16) {
12142 		goto skip_fastpath;
12143 	}
12144 
12145 	/* Align 'p' to 4; the input data may have arbitrary alignment.
12146 	 * End of string check not needed because blen >= 16.
12147 	 */
12148 	while (((duk_size_t) (const void *) p) & 0x03U) {
12149 		duk_uint8_t x;
12150 		x = *p++;
12151 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12152 			ncont++;
12153 		}
12154 	}
12155 
12156 	/* Full, aligned 4-byte reads. */
12157 	p32_end = (const duk_uint32_t *) (const void *) (p + ((duk_size_t) (p_end - p) & (duk_size_t) (~0x03)));
12158 	p32 = (const duk_uint32_t *) (const void *) p;
12159 	while (p32 != (const duk_uint32_t *) p32_end) {
12160 		duk_uint32_t x;
12161 		x = *p32++;
12162 		if (DUK_LIKELY((x & 0x80808080UL) == 0)) {
12163 			;  /* ASCII fast path */
12164 		} else {
12165 			/* Flip highest bit of each byte which changes
12166 			 * the bit pattern 10xxxxxx into 00xxxxxx which
12167 			 * allows an easy bit mask test.
12168 			 */
12169 			x ^= 0x80808080UL;
12170 			if (DUK_UNLIKELY(!(x & 0xc0000000UL))) {
12171 				ncont++;
12172 			}
12173 			if (DUK_UNLIKELY(!(x & 0x00c00000UL))) {
12174 				ncont++;
12175 			}
12176 			if (DUK_UNLIKELY(!(x & 0x0000c000UL))) {
12177 				ncont++;
12178 			}
12179 			if (DUK_UNLIKELY(!(x & 0x000000c0UL))) {
12180 				ncont++;
12181 			}
12182 		}
12183 	}
12184 	p = (const duk_uint8_t *) p32;
12185 	/* Fall through to handle the rest. */
12186 
12187  skip_fastpath:
12188 	while (p != p_end) {
12189 		duk_uint8_t x;
12190 		x = *p++;
12191 		if (DUK_UNLIKELY(x >= 0x80 && x <= 0xbf)) {
12192 			ncont++;
12193 		}
12194 	}
12195 
12196 	DUK_ASSERT(ncont <= blen);
12197 	clen = blen - ncont;
12198 	DUK_ASSERT(clen <= blen);
12199 	return clen;
12200 }
12201 #endif  /* DUK_USE_PREFER_SIZE */
12202 
12203 /*
12204  *  Unicode range matcher
12205  *
12206  *  Matches a codepoint against a packed bitstream of character ranges.
12207  *  Used for slow path Unicode matching.
12208  */
12209 
12210 /* Must match tools/extract_chars.py, generate_match_table3(). */
duk__uni_decode_value(duk_bitdecoder_ctx * bd_ctx)12211 DUK_LOCAL duk_uint32_t duk__uni_decode_value(duk_bitdecoder_ctx *bd_ctx) {
12212 	duk_uint32_t t;
12213 
12214 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 4);
12215 	if (t <= 0x0eU) {
12216 		return t;
12217 	}
12218 	t = (duk_uint32_t) duk_bd_decode(bd_ctx, 8);
12219 	if (t <= 0xfdU) {
12220 		return t + 0x0f;
12221 	}
12222 	if (t == 0xfeU) {
12223 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 12);
12224 		return t + 0x0fU + 0xfeU;
12225 	} else {
12226 		t = (duk_uint32_t) duk_bd_decode(bd_ctx, 24);
12227 		return t + 0x0fU + 0xfeU + 0x1000UL;
12228 	}
12229 }
12230 
duk__uni_range_match(const duk_uint8_t * unitab,duk_size_t unilen,duk_codepoint_t cp)12231 DUK_LOCAL duk_small_int_t duk__uni_range_match(const duk_uint8_t *unitab, duk_size_t unilen, duk_codepoint_t cp) {
12232 	duk_bitdecoder_ctx bd_ctx;
12233 	duk_codepoint_t prev_re;
12234 
12235 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12236 	bd_ctx.data = (const duk_uint8_t *) unitab;
12237 	bd_ctx.length = (duk_size_t) unilen;
12238 
12239 	prev_re = 0;
12240 	for (;;) {
12241 		duk_codepoint_t r1, r2;
12242 		r1 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12243 		if (r1 == 0) {
12244 			break;
12245 		}
12246 		r2 = (duk_codepoint_t) duk__uni_decode_value(&bd_ctx);
12247 
12248 		r1 = prev_re + r1;
12249 		r2 = r1 + r2;
12250 		prev_re = r2;
12251 
12252 		/* [r1,r2] is the range */
12253 
12254 		DUK_DDD(DUK_DDDPRINT("duk__uni_range_match: cp=%06lx range=[0x%06lx,0x%06lx]",
12255 		                     (unsigned long) cp, (unsigned long) r1, (unsigned long) r2));
12256 		if (cp >= r1 && cp <= r2) {
12257 			return 1;
12258 		}
12259 	}
12260 
12261 	return 0;
12262 }
12263 
12264 /*
12265  *  "WhiteSpace" production check.
12266  */
12267 
duk_unicode_is_whitespace(duk_codepoint_t cp)12268 DUK_INTERNAL duk_small_int_t duk_unicode_is_whitespace(duk_codepoint_t cp) {
12269 	/*
12270 	 *  E5 Section 7.2 specifies six characters specifically as
12271 	 *  white space:
12272 	 *
12273 	 *    0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATION;;;;
12274 	 *    000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;
12275 	 *    000C;<control>;Cc;0;WS;;;;;N;FORM FEED (FF);;;;
12276 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12277 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12278 	 *    FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;;
12279 	 *
12280 	 *  It also specifies any Unicode category 'Zs' characters as white
12281 	 *  space.  These can be extracted with the "tools/extract_chars.py" script.
12282 	 *  Current result:
12283 	 *
12284 	 *    RAW OUTPUT:
12285 	 *    ===========
12286 	 *    0020;SPACE;Zs;0;WS;;;;;N;;;;;
12287 	 *    00A0;NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;NON-BREAKING SPACE;;;;
12288 	 *    1680;OGHAM SPACE MARK;Zs;0;WS;;;;;N;;;;;
12289 	 *    180E;MONGOLIAN VOWEL SEPARATOR;Zs;0;WS;;;;;N;;;;;
12290 	 *    2000;EN QUAD;Zs;0;WS;2002;;;;N;;;;;
12291 	 *    2001;EM QUAD;Zs;0;WS;2003;;;;N;;;;;
12292 	 *    2002;EN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12293 	 *    2003;EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12294 	 *    2004;THREE-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12295 	 *    2005;FOUR-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12296 	 *    2006;SIX-PER-EM SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12297 	 *    2007;FIGURE SPACE;Zs;0;WS;<noBreak> 0020;;;;N;;;;;
12298 	 *    2008;PUNCTUATION SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12299 	 *    2009;THIN SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12300 	 *    200A;HAIR SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12301 	 *    202F;NARROW NO-BREAK SPACE;Zs;0;CS;<noBreak> 0020;;;;N;;;;;
12302 	 *    205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS;<compat> 0020;;;;N;;;;;
12303 	 *    3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
12304 	 *
12305 	 *    RANGES:
12306 	 *    =======
12307 	 *    0x0020
12308 	 *    0x00a0
12309 	 *    0x1680
12310 	 *    0x180e
12311 	 *    0x2000 ... 0x200a
12312 	 *    0x202f
12313 	 *    0x205f
12314 	 *    0x3000
12315 	 *
12316 	 *  A manual decoder (below) is probably most compact for this.
12317 	 */
12318 
12319 	duk_uint_fast8_t lo;
12320 	duk_uint_fast32_t hi;
12321 
12322 	/* cp == -1 (EOF) never matches and causes return value 0 */
12323 
12324 	lo = (duk_uint_fast8_t) (cp & 0xff);
12325 	hi = (duk_uint_fast32_t) (cp >> 8);  /* does not fit into an uchar */
12326 
12327 	if (hi == 0x0000UL) {
12328 		if (lo == 0x09U || lo == 0x0bU || lo == 0x0cU ||
12329 		    lo == 0x20U || lo == 0xa0U) {
12330 			return 1;
12331 		}
12332 	} else if (hi == 0x0020UL) {
12333 		if (lo <= 0x0aU || lo == 0x2fU || lo == 0x5fU) {
12334 			return 1;
12335 		}
12336 	} else if (cp == 0x1680L || cp == 0x180eL || cp == 0x3000L ||
12337 	           cp == 0xfeffL) {
12338 		return 1;
12339 	}
12340 
12341 	return 0;
12342 }
12343 
12344 /*
12345  *  "LineTerminator" production check.
12346  */
12347 
duk_unicode_is_line_terminator(duk_codepoint_t cp)12348 DUK_INTERNAL duk_small_int_t duk_unicode_is_line_terminator(duk_codepoint_t cp) {
12349 	/*
12350 	 *  E5 Section 7.3
12351 	 *
12352 	 *  A LineTerminatorSequence essentially merges <CR> <LF> sequences
12353 	 *  into a single line terminator.  This must be handled by the caller.
12354 	 */
12355 
12356 	if (cp == 0x000aL || cp == 0x000dL || cp == 0x2028L ||
12357 	    cp == 0x2029L) {
12358 		return 1;
12359 	}
12360 
12361 	return 0;
12362 }
12363 
12364 /*
12365  *  "IdentifierStart" production check.
12366  */
12367 
duk_unicode_is_identifier_start(duk_codepoint_t cp)12368 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_start(duk_codepoint_t cp) {
12369 	/*
12370 	 *  E5 Section 7.6:
12371 	 *
12372 	 *    IdentifierStart:
12373 	 *      UnicodeLetter
12374 	 *      $
12375 	 *      _
12376 	 *      \ UnicodeEscapeSequence
12377 	 *
12378 	 *  IdentifierStart production has one multi-character production:
12379 	 *
12380 	 *    \ UnicodeEscapeSequence
12381 	 *
12382 	 *  The '\' character is -not- matched by this function.  Rather, the caller
12383 	 *  should decode the escape and then call this function to check whether the
12384 	 *  decoded character is acceptable (see discussion in E5 Section 7.6).
12385 	 *
12386 	 *  The "UnicodeLetter" alternative of the production allows letters
12387 	 *  from various Unicode categories.  These can be extracted with the
12388 	 *  "tools/extract_chars.py" script.
12389 	 *
12390 	 *  Because the result has hundreds of Unicode codepoint ranges, matching
12391 	 *  for any values >= 0x80 are done using a very slow range-by-range scan
12392 	 *  and a packed range format.
12393 	 *
12394 	 *  The ASCII portion (codepoints 0x00 ... 0x7f) is fast-pathed below because
12395 	 *  it matters the most.  The ASCII related ranges of IdentifierStart are:
12396 	 *
12397 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12398 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12399 	 *    0x0024                ['$']
12400 	 *    0x005f                ['_']
12401 	 */
12402 
12403 	/* ASCII (and EOF) fast path -- quick accept and reject */
12404 	if (cp <= 0x7fL) {
12405 #if defined(DUK_USE_IDCHAR_FASTPATH)
12406 		return (cp >= 0) && (duk_is_idchar_tab[cp] > 0);
12407 #else
12408 		if ((cp >= 'a' && cp <= 'z') ||
12409 		    (cp >= 'A' && cp <= 'Z') ||
12410 		    cp == '_' || cp == '$') {
12411 			return 1;
12412 		}
12413 		return 0;
12414 #endif
12415 	}
12416 
12417 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12418 
12419 #if defined(DUK_USE_SOURCE_NONBMP)
12420 	if (duk__uni_range_match(duk_unicode_ids_noa,
12421 	                         (duk_size_t) sizeof(duk_unicode_ids_noa),
12422 	                         (duk_codepoint_t) cp)) {
12423 		return 1;
12424 	}
12425 	return 0;
12426 #else
12427 	if (cp < 0x10000L) {
12428 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12429 		                         sizeof(duk_unicode_ids_noabmp),
12430 		                         (duk_codepoint_t) cp)) {
12431 			return 1;
12432 		}
12433 		return 0;
12434 	} else {
12435 		/* without explicit non-BMP support, assume non-BMP characters
12436 		 * are always accepted as identifier characters.
12437 		 */
12438 		return 1;
12439 	}
12440 #endif
12441 }
12442 
12443 /*
12444  *  "IdentifierPart" production check.
12445  */
12446 
duk_unicode_is_identifier_part(duk_codepoint_t cp)12447 DUK_INTERNAL duk_small_int_t duk_unicode_is_identifier_part(duk_codepoint_t cp) {
12448 	/*
12449 	 *  E5 Section 7.6:
12450 	 *
12451 	 *    IdentifierPart:
12452 	 *      IdentifierStart
12453 	 *      UnicodeCombiningMark
12454 	 *      UnicodeDigit
12455 	 *      UnicodeConnectorPunctuation
12456 	 *      <ZWNJ>  [U+200C]
12457 	 *      <ZWJ>   [U+200D]
12458 	 *
12459 	 *  IdentifierPart production has one multi-character production
12460 	 *  as part of its IdentifierStart alternative.  The '\' character
12461 	 *  of an escape sequence is not matched here, see discussion in
12462 	 *  duk_unicode_is_identifier_start().
12463 	 *
12464 	 *  To match non-ASCII characters (codepoints >= 0x80), a very slow
12465 	 *  linear range-by-range scan is used.  The codepoint is first compared
12466 	 *  to the IdentifierStart ranges, and if it doesn't match, then to a
12467 	 *  set consisting of code points in IdentifierPart but not in
12468 	 *  IdentifierStart.  This is done to keep the unicode range data small,
12469 	 *  at the expense of speed.
12470 	 *
12471 	 *  The ASCII fast path consists of:
12472 	 *
12473 	 *    0x0030 ... 0x0039     ['0' ... '9', UnicodeDigit]
12474 	 *    0x0041 ... 0x005a     ['A' ... 'Z', IdentifierStart]
12475 	 *    0x0061 ... 0x007a     ['a' ... 'z', IdentifierStart]
12476 	 *    0x0024                ['$', IdentifierStart]
12477 	 *    0x005f                ['_', IdentifierStart and
12478 	 *                                UnicodeConnectorPunctuation]
12479 	 *
12480 	 *  UnicodeCombiningMark has no code points <= 0x7f.
12481 	 *
12482 	 *  The matching code reuses the "identifier start" tables, and then
12483 	 *  consults a separate range set for characters in "identifier part"
12484 	 *  but not in "identifier start".  These can be extracted with the
12485 	 *  "tools/extract_chars.py" script.
12486 	 *
12487 	 *  UnicodeCombiningMark -> categories Mn, Mc
12488 	 *  UnicodeDigit -> categories Nd
12489 	 *  UnicodeConnectorPunctuation -> categories Pc
12490 	 */
12491 
12492 	/* ASCII (and EOF) fast path -- quick accept and reject */
12493 	if (cp <= 0x7fL) {
12494 #if defined(DUK_USE_IDCHAR_FASTPATH)
12495 		return (cp >= 0) && (duk_is_idchar_tab[cp] != 0);
12496 #else
12497 		if ((cp >= 'a' && cp <= 'z') ||
12498 		    (cp >= 'A' && cp <= 'Z') ||
12499 		    (cp >= '0' && cp <= '9') ||
12500 		    cp == '_' || cp == '$') {
12501 			return 1;
12502 		}
12503 		return 0;
12504 #endif
12505 	}
12506 
12507 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12508 
12509 #if defined(DUK_USE_SOURCE_NONBMP)
12510 	if (duk__uni_range_match(duk_unicode_ids_noa,
12511 	                         sizeof(duk_unicode_ids_noa),
12512 	                         (duk_codepoint_t) cp) ||
12513 	    duk__uni_range_match(duk_unicode_idp_m_ids_noa,
12514 	                         sizeof(duk_unicode_idp_m_ids_noa),
12515 	                         (duk_codepoint_t) cp)) {
12516 		return 1;
12517 	}
12518 	return 0;
12519 #else
12520 	if (cp < 0x10000L) {
12521 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12522 		                         sizeof(duk_unicode_ids_noabmp),
12523 		                         (duk_codepoint_t) cp) ||
12524 		    duk__uni_range_match(duk_unicode_idp_m_ids_noabmp,
12525 		                         sizeof(duk_unicode_idp_m_ids_noabmp),
12526 		                         (duk_codepoint_t) cp)) {
12527 			return 1;
12528 		}
12529 		return 0;
12530 	} else {
12531 		/* without explicit non-BMP support, assume non-BMP characters
12532 		 * are always accepted as identifier characters.
12533 		 */
12534 		return 1;
12535 	}
12536 #endif
12537 }
12538 
12539 /*
12540  *  Unicode letter check.
12541  */
12542 
duk_unicode_is_letter(duk_codepoint_t cp)12543 DUK_INTERNAL duk_small_int_t duk_unicode_is_letter(duk_codepoint_t cp) {
12544 	/*
12545 	 *  Unicode letter is now taken to be the categories:
12546 	 *
12547 	 *    Lu, Ll, Lt, Lm, Lo
12548 	 *
12549 	 *  (Not sure if this is exactly correct.)
12550 	 *
12551 	 *  The ASCII fast path consists of:
12552 	 *
12553 	 *    0x0041 ... 0x005a     ['A' ... 'Z']
12554 	 *    0x0061 ... 0x007a     ['a' ... 'z']
12555 	 */
12556 
12557 	/* ASCII (and EOF) fast path -- quick accept and reject */
12558 	if (cp <= 0x7fL) {
12559 		if ((cp >= 'a' && cp <= 'z') ||
12560 		    (cp >= 'A' && cp <= 'Z')) {
12561 			return 1;
12562 		}
12563 		return 0;
12564 	}
12565 
12566 	/* Non-ASCII slow path (range-by-range linear comparison), very slow */
12567 
12568 #if defined(DUK_USE_SOURCE_NONBMP)
12569 	if (duk__uni_range_match(duk_unicode_ids_noa,
12570 	                         sizeof(duk_unicode_ids_noa),
12571 	                         (duk_codepoint_t) cp) &&
12572 	    !duk__uni_range_match(duk_unicode_ids_m_let_noa,
12573 	                          sizeof(duk_unicode_ids_m_let_noa),
12574 	                          (duk_codepoint_t) cp)) {
12575 		return 1;
12576 	}
12577 	return 0;
12578 #else
12579 	if (cp < 0x10000L) {
12580 		if (duk__uni_range_match(duk_unicode_ids_noabmp,
12581 		                         sizeof(duk_unicode_ids_noabmp),
12582 		                         (duk_codepoint_t) cp) &&
12583 		    !duk__uni_range_match(duk_unicode_ids_m_let_noabmp,
12584 		                          sizeof(duk_unicode_ids_m_let_noabmp),
12585 		                          (duk_codepoint_t) cp)) {
12586 			return 1;
12587 		}
12588 		return 0;
12589 	} else {
12590 		/* without explicit non-BMP support, assume non-BMP characters
12591 		 * are always accepted as letters.
12592 		 */
12593 		return 1;
12594 	}
12595 #endif
12596 }
12597 
12598 /*
12599  *  Complex case conversion helper which decodes a bit-packed conversion
12600  *  control stream generated by tools/extract_caseconv.py.  The conversion
12601  *  is very slow because it runs through the conversion data in a linear
12602  *  fashion to save space (which is why ASCII characters have a special
12603  *  fast path before arriving here).
12604  *
12605  *  The particular bit counts etc have been determined experimentally to
12606  *  be small but still sufficient, and must match the Python script
12607  *  (tools/extract_caseconv.py).
12608  *
12609  *  The return value is the case converted codepoint or -1 if the conversion
12610  *  results in multiple characters (this is useful for regexp Canonicalization
12611  *  operation).  If 'buf' is not NULL, the result codepoint(s) are also
12612  *  appended to the hbuffer.
12613  *
12614  *  Context and locale specific rules must be checked before consulting
12615  *  this function.
12616  */
12617 
12618 DUK_LOCAL
duk__slow_case_conversion(duk_hthread * thr,duk_bufwriter_ctx * bw,duk_codepoint_t cp,duk_bitdecoder_ctx * bd_ctx)12619 duk_codepoint_t duk__slow_case_conversion(duk_hthread *thr,
12620                                           duk_bufwriter_ctx *bw,
12621                                           duk_codepoint_t cp,
12622                                           duk_bitdecoder_ctx *bd_ctx) {
12623 	duk_small_int_t skip = 0;
12624 	duk_small_int_t n;
12625 	duk_small_int_t t;
12626 	duk_small_int_t count;
12627 	duk_codepoint_t tmp_cp;
12628 	duk_codepoint_t start_i;
12629 	duk_codepoint_t start_o;
12630 
12631 	DUK_ASSERT(bd_ctx != NULL);
12632 	DUK_UNREF(thr);
12633 
12634 	DUK_DDD(DUK_DDDPRINT("slow case conversion for codepoint: %ld", (long) cp));
12635 
12636 	/* range conversion with a "skip" */
12637 	DUK_DDD(DUK_DDDPRINT("checking ranges"));
12638 	for (;;) {
12639 		skip++;
12640 		n = (duk_small_int_t) duk_bd_decode(bd_ctx, 6);
12641 		if (n == 0x3f) {
12642 			/* end marker */
12643 			break;
12644 		}
12645 		DUK_DDD(DUK_DDDPRINT("skip=%ld, n=%ld", (long) skip, (long) n));
12646 
12647 		while (n--) {
12648 			start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12649 			start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12650 			count = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12651 			DUK_DDD(DUK_DDDPRINT("range: start_i=%ld, start_o=%ld, count=%ld, skip=%ld",
12652 			                     (long) start_i, (long) start_o, (long) count, (long) skip));
12653 
12654 			if (cp >= start_i) {
12655 				tmp_cp = cp - start_i;  /* always >= 0 */
12656 				if (tmp_cp < (duk_codepoint_t) count * (duk_codepoint_t) skip &&
12657 				    (tmp_cp % (duk_codepoint_t) skip) == 0) {
12658 					DUK_DDD(DUK_DDDPRINT("range matches input codepoint"));
12659 					cp = start_o + tmp_cp;
12660 					goto single;
12661 				}
12662 			}
12663 		}
12664 	}
12665 
12666 	/* 1:1 conversion */
12667 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12668 	DUK_DDD(DUK_DDDPRINT("checking 1:1 conversions (count %ld)", (long) n));
12669 	while (n--) {
12670 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12671 		start_o = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12672 		DUK_DDD(DUK_DDDPRINT("1:1 conversion %ld -> %ld", (long) start_i, (long) start_o));
12673 		if (cp == start_i) {
12674 			DUK_DDD(DUK_DDDPRINT("1:1 matches input codepoint"));
12675 			cp = start_o;
12676 			goto single;
12677 		}
12678 	}
12679 
12680 	/* complex, multicharacter conversion */
12681 	n = (duk_small_int_t) duk_bd_decode(bd_ctx, 7);
12682 	DUK_DDD(DUK_DDDPRINT("checking 1:n conversions (count %ld)", (long) n));
12683 	while (n--) {
12684 		start_i = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12685 		t = (duk_small_int_t) duk_bd_decode(bd_ctx, 2);
12686 		DUK_DDD(DUK_DDDPRINT("1:n conversion %ld -> %ld chars", (long) start_i, (long) t));
12687 		if (cp == start_i) {
12688 			DUK_DDD(DUK_DDDPRINT("1:n matches input codepoint"));
12689 			if (bw != NULL) {
12690 				while (t--) {
12691 					tmp_cp = (duk_codepoint_t) duk_bd_decode(bd_ctx, 16);
12692 					DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) tmp_cp);
12693 				}
12694 			}
12695 			return -1;
12696 		} else {
12697 			while (t--) {
12698 				(void) duk_bd_decode(bd_ctx, 16);
12699 			}
12700 		}
12701 	}
12702 
12703 	/* default: no change */
12704 	DUK_DDD(DUK_DDDPRINT("no rule matches, output is same as input"));
12705 	/* fall through */
12706 
12707  single:
12708 	if (bw != NULL) {
12709 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12710 	}
12711 	return cp;
12712 }
12713 
12714 /*
12715  *  Case conversion helper, with context/local sensitivity.
12716  *  For proper case conversion, one needs to know the character
12717  *  and the preceding and following characters, as well as
12718  *  locale/language.
12719  */
12720 
12721 /* XXX: add 'language' argument when locale/language sensitive rule
12722  * support added.
12723  */
12724 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)12725 duk_codepoint_t duk__case_transform_helper(duk_hthread *thr,
12726                                            duk_bufwriter_ctx *bw,
12727                                            duk_codepoint_t cp,
12728                                            duk_codepoint_t prev,
12729                                            duk_codepoint_t next,
12730                                            duk_bool_t uppercase) {
12731 	duk_bitdecoder_ctx bd_ctx;
12732 
12733 	/* fast path for ASCII */
12734 	if (cp < 0x80L) {
12735 		/* XXX: there are language sensitive rules for the ASCII range.
12736 		 * If/when language/locale support is implemented, they need to
12737 		 * be implemented here for the fast path.  There are no context
12738 		 * sensitive rules for ASCII range.
12739 		 */
12740 
12741 		if (uppercase) {
12742 			if (cp >= 'a' && cp <= 'z') {
12743 				cp = cp - 'a' + 'A';
12744 			}
12745 		} else {
12746 			if (cp >= 'A' && cp <= 'Z') {
12747 				cp = cp - 'A' + 'a';
12748 			}
12749 		}
12750 
12751 		if (bw != NULL) {
12752 			DUK_BW_WRITE_RAW_U8(thr, bw, (duk_uint8_t) cp);
12753 		}
12754 		return cp;
12755 	}
12756 
12757 	/* context and locale specific rules which cannot currently be represented
12758 	 * in the caseconv bitstream: hardcoded rules in C
12759 	 */
12760 	if (uppercase) {
12761 		/* XXX: turkish / azeri */
12762 	} else {
12763 		/*
12764 		 *  Final sigma context specific rule.  This is a rather tricky
12765 		 *  rule and this handling is probably not 100% correct now.
12766 		 *  The rule is not locale/language specific so it is supported.
12767 		 */
12768 
12769 		if (cp == 0x03a3L &&    /* U+03A3 = GREEK CAPITAL LETTER SIGMA */
12770 		    duk_unicode_is_letter(prev) &&        /* prev exists and is not a letter */
12771 		    !duk_unicode_is_letter(next)) {       /* next does not exist or next is not a letter */
12772 			/* Capital sigma occurred at "end of word", lowercase to
12773 			 * U+03C2 = GREEK SMALL LETTER FINAL SIGMA.  Otherwise
12774 			 * fall through and let the normal rules lowercase it to
12775 			 * U+03C3 = GREEK SMALL LETTER SIGMA.
12776 			 */
12777 			cp = 0x03c2L;
12778 			goto singlechar;
12779 		}
12780 
12781 		/* XXX: lithuanian not implemented */
12782 		/* XXX: lithuanian, explicit dot rules */
12783 		/* XXX: turkish / azeri, lowercase rules */
12784 	}
12785 
12786 	/* 1:1 or special conversions, but not locale/context specific: script generated rules */
12787 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
12788 	if (uppercase) {
12789 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_uc;
12790 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_uc);
12791 	} else {
12792 		bd_ctx.data = (const duk_uint8_t *) duk_unicode_caseconv_lc;
12793 		bd_ctx.length = (duk_size_t) sizeof(duk_unicode_caseconv_lc);
12794 	}
12795 	return duk__slow_case_conversion(thr, bw, cp, &bd_ctx);
12796 
12797  singlechar:
12798 	if (bw != NULL) {
12799 		DUK_BW_WRITE_RAW_XUTF8(thr, bw, (duk_ucodepoint_t) cp);
12800 	}
12801 	return cp;
12802 
12803  /* unused now, not needed until Turkish/Azeri */
12804 #if 0
12805  nochar:
12806 	return -1;
12807 #endif
12808 }
12809 
12810 /*
12811  *  Replace valstack top with case converted version.
12812  */
12813 
duk_unicode_case_convert_string(duk_hthread * thr,duk_bool_t uppercase)12814 DUK_INTERNAL void duk_unicode_case_convert_string(duk_hthread *thr, duk_bool_t uppercase) {
12815 	duk_hstring *h_input;
12816 	duk_bufwriter_ctx bw_alloc;
12817 	duk_bufwriter_ctx *bw;
12818 	const duk_uint8_t *p, *p_start, *p_end;
12819 	duk_codepoint_t prev, curr, next;
12820 
12821 	h_input = duk_require_hstring(thr, -1);  /* Accept symbols. */
12822 	DUK_ASSERT(h_input != NULL);
12823 
12824 	bw = &bw_alloc;
12825 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));
12826 
12827 	/* [ ... input buffer ] */
12828 
12829 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
12830 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
12831 	p = p_start;
12832 
12833 	prev = -1; DUK_UNREF(prev);
12834 	curr = -1;
12835 	next = -1;
12836 	for (;;) {
12837 		prev = curr;
12838 		curr = next;
12839 		next = -1;
12840 		if (p < p_end) {
12841 			next = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
12842 		} else {
12843 			/* end of input and last char has been processed */
12844 			if (curr < 0) {
12845 				break;
12846 			}
12847 		}
12848 
12849 		/* on first round, skip */
12850 		if (curr >= 0) {
12851 			/* XXX: could add a fast path to process chunks of input codepoints,
12852 			 * but relative benefit would be quite small.
12853 			 */
12854 
12855 			/* Ensure space for maximum multi-character result; estimate is overkill. */
12856 			DUK_BW_ENSURE(thr, bw, 8 * DUK_UNICODE_MAX_XUTF8_LENGTH);
12857 
12858 			duk__case_transform_helper(thr,
12859 			                           bw,
12860 			                           (duk_codepoint_t) curr,
12861 			                           prev,
12862 			                           next,
12863 			                           uppercase);
12864 		}
12865 	}
12866 
12867 	DUK_BW_COMPACT(thr, bw);
12868 	(void) duk_buffer_to_string(thr, -1);  /* Safe, output is encoded. */
12869 	/* invalidates h_buf pointer */
12870 	duk_remove_m2(thr);
12871 }
12872 
12873 #if defined(DUK_USE_REGEXP_SUPPORT)
12874 
12875 /*
12876  *  Canonicalize() abstract operation needed for canonicalization of individual
12877  *  codepoints during regexp compilation and execution, see E5 Section 15.10.2.8.
12878  *  Note that codepoints are canonicalized one character at a time, so no context
12879  *  specific rules can apply.  Locale specific rules can apply, though.
12880  */
12881 
duk_unicode_re_canonicalize_char(duk_hthread * thr,duk_codepoint_t cp)12882 DUK_INTERNAL duk_codepoint_t duk_unicode_re_canonicalize_char(duk_hthread *thr, duk_codepoint_t cp) {
12883 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
12884 	/* Fast canonicalization lookup at the cost of 128kB footprint. */
12885 	DUK_ASSERT(cp >= 0);
12886 	DUK_UNREF(thr);
12887 	if (DUK_LIKELY(cp < 0x10000L)) {
12888 		return (duk_codepoint_t) duk_unicode_re_canon_lookup[cp];
12889 	}
12890 	return cp;
12891 #else  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12892 	duk_codepoint_t y;
12893 
12894 	y = duk__case_transform_helper(thr,
12895 	                               NULL,    /* NULL is allowed, no output */
12896 	                               cp,      /* curr char */
12897 	                               -1,      /* prev char */
12898 	                               -1,      /* next char */
12899 	                               1);      /* uppercase */
12900 
12901 	if ((y < 0) || (cp >= 0x80 && y < 0x80)) {
12902 		/* multiple codepoint conversion or non-ASCII mapped to ASCII
12903 		 * --> leave as is.
12904 		 */
12905 		return cp;
12906 	}
12907 
12908 	return y;
12909 #endif  /* DUK_USE_REGEXP_CANON_WORKAROUND */
12910 }
12911 
12912 /*
12913  *  E5 Section 15.10.2.6 "IsWordChar" abstract operation.  Assume
12914  *  x < 0 for characters read outside the string.
12915  */
12916 
duk_unicode_re_is_wordchar(duk_codepoint_t x)12917 DUK_INTERNAL duk_small_int_t duk_unicode_re_is_wordchar(duk_codepoint_t x) {
12918 	/*
12919 	 *  Note: the description in E5 Section 15.10.2.6 has a typo, it
12920 	 *  contains 'A' twice and lacks 'a'; the intent is [0-9a-zA-Z_].
12921 	 */
12922 	if ((x >= '0' && x <= '9') ||
12923 	    (x >= 'a' && x <= 'z') ||
12924 	    (x >= 'A' && x <= 'Z') ||
12925 	    (x == '_')) {
12926 		return 1;
12927 	}
12928 	return 0;
12929 }
12930 
12931 /*
12932  *  Regexp range tables
12933  */
12934 
12935 /* exposed because lexer needs these too */
12936 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_digit[2] = {
12937 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12938 };
12939 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_white[22] = {
12940 	(duk_uint16_t) 0x0009UL, (duk_uint16_t) 0x000DUL,
12941 	(duk_uint16_t) 0x0020UL, (duk_uint16_t) 0x0020UL,
12942 	(duk_uint16_t) 0x00A0UL, (duk_uint16_t) 0x00A0UL,
12943 	(duk_uint16_t) 0x1680UL, (duk_uint16_t) 0x1680UL,
12944 	(duk_uint16_t) 0x180EUL, (duk_uint16_t) 0x180EUL,
12945 	(duk_uint16_t) 0x2000UL, (duk_uint16_t) 0x200AUL,
12946 	(duk_uint16_t) 0x2028UL, (duk_uint16_t) 0x2029UL,
12947 	(duk_uint16_t) 0x202FUL, (duk_uint16_t) 0x202FUL,
12948 	(duk_uint16_t) 0x205FUL, (duk_uint16_t) 0x205FUL,
12949 	(duk_uint16_t) 0x3000UL, (duk_uint16_t) 0x3000UL,
12950 	(duk_uint16_t) 0xFEFFUL, (duk_uint16_t) 0xFEFFUL,
12951 };
12952 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_wordchar[8] = {
12953 	(duk_uint16_t) 0x0030UL, (duk_uint16_t) 0x0039UL,
12954 	(duk_uint16_t) 0x0041UL, (duk_uint16_t) 0x005AUL,
12955 	(duk_uint16_t) 0x005FUL, (duk_uint16_t) 0x005FUL,
12956 	(duk_uint16_t) 0x0061UL, (duk_uint16_t) 0x007AUL,
12957 };
12958 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_digit[4] = {
12959 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12960 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0xFFFFUL,
12961 };
12962 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_white[24] = {
12963 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x0008UL,
12964 	(duk_uint16_t) 0x000EUL, (duk_uint16_t) 0x001FUL,
12965 	(duk_uint16_t) 0x0021UL, (duk_uint16_t) 0x009FUL,
12966 	(duk_uint16_t) 0x00A1UL, (duk_uint16_t) 0x167FUL,
12967 	(duk_uint16_t) 0x1681UL, (duk_uint16_t) 0x180DUL,
12968 	(duk_uint16_t) 0x180FUL, (duk_uint16_t) 0x1FFFUL,
12969 	(duk_uint16_t) 0x200BUL, (duk_uint16_t) 0x2027UL,
12970 	(duk_uint16_t) 0x202AUL, (duk_uint16_t) 0x202EUL,
12971 	(duk_uint16_t) 0x2030UL, (duk_uint16_t) 0x205EUL,
12972 	(duk_uint16_t) 0x2060UL, (duk_uint16_t) 0x2FFFUL,
12973 	(duk_uint16_t) 0x3001UL, (duk_uint16_t) 0xFEFEUL,
12974 	(duk_uint16_t) 0xFF00UL, (duk_uint16_t) 0xFFFFUL,
12975 };
12976 DUK_INTERNAL const duk_uint16_t duk_unicode_re_ranges_not_wordchar[10] = {
12977 	(duk_uint16_t) 0x0000UL, (duk_uint16_t) 0x002FUL,
12978 	(duk_uint16_t) 0x003AUL, (duk_uint16_t) 0x0040UL,
12979 	(duk_uint16_t) 0x005BUL, (duk_uint16_t) 0x005EUL,
12980 	(duk_uint16_t) 0x0060UL, (duk_uint16_t) 0x0060UL,
12981 	(duk_uint16_t) 0x007BUL, (duk_uint16_t) 0xFFFFUL,
12982 };
12983 
12984 #endif  /* DUK_USE_REGEXP_SUPPORT */
12985 #line 1 "duk_util_misc.c"
12986 /*
12987  *  Misc util stuff.
12988  */
12989 
12990 /* #include duk_internal.h -> already included */
12991 
12992 /*
12993  *  Lowercase digits for radix values 2 to 36.  Also doubles as lowercase
12994  *  hex nybble table.
12995  */
12996 
12997 DUK_INTERNAL const duk_uint8_t duk_lc_digits[36] = {
12998 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
12999 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13000 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_LC_A, DUK_ASC_LC_B,
13001 	DUK_ASC_LC_C, DUK_ASC_LC_D, DUK_ASC_LC_E, DUK_ASC_LC_F,
13002 	DUK_ASC_LC_G, DUK_ASC_LC_H, DUK_ASC_LC_I, DUK_ASC_LC_J,
13003 	DUK_ASC_LC_K, DUK_ASC_LC_L, DUK_ASC_LC_M, DUK_ASC_LC_N,
13004 	DUK_ASC_LC_O, DUK_ASC_LC_P, DUK_ASC_LC_Q, DUK_ASC_LC_R,
13005 	DUK_ASC_LC_S, DUK_ASC_LC_T, DUK_ASC_LC_U, DUK_ASC_LC_V,
13006 	DUK_ASC_LC_W, DUK_ASC_LC_X, DUK_ASC_LC_Y, DUK_ASC_LC_Z
13007 };
13008 
13009 DUK_INTERNAL const duk_uint8_t duk_uc_nybbles[16] = {
13010 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
13011 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
13012 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UC_A, DUK_ASC_UC_B,
13013 	DUK_ASC_UC_C, DUK_ASC_UC_D, DUK_ASC_UC_E, DUK_ASC_UC_F
13014 };
13015 
13016 /*
13017  *  Table for hex decoding ASCII hex digits
13018  */
13019 
13020 DUK_INTERNAL const duk_int8_t duk_hex_dectab[256] = {
13021 	/* -1 if invalid */
13022 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x00-0x0f */
13023 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x10-0x1f */
13024 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x20-0x2f */
13025 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,  /* 0x30-0x3f */
13026 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x40-0x4f */
13027 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x50-0x5f */
13028 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x60-0x6f */
13029 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x70-0x7f */
13030 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x80-0x8f */
13031 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0x90-0x9f */
13032 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xa0-0xaf */
13033 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xb0-0xbf */
13034 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xc0-0xcf */
13035 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xd0-0xdf */
13036 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  /* 0xe0-0xef */
13037 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1   /* 0xf0-0xff */
13038 };
13039 
13040 #if defined(DUK_USE_HEX_FASTPATH)
13041 /* Preshifted << 4.  Must use 16-bit entry to allow negative value signaling. */
13042 DUK_INTERNAL const duk_int16_t duk_hex_dectab_shift4[256] = {
13043 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x00-0x0f */
13044 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x10-0x1f */
13045 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x20-0x2f */
13046 	0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x30-0x3f */
13047 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x40-0x4f */
13048 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x50-0x5f */
13049 	  -1, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x60-0x6f */
13050 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x70-0x7f */
13051 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x80-0x8f */
13052 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0x90-0x9f */
13053 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xa0-0xaf */
13054 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xb0-0xbf */
13055 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xc0-0xcf */
13056 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xd0-0xdf */
13057 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  /* 0xe0-0xef */
13058 	  -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1   /* 0xf0-0xff */
13059 };
13060 #endif
13061 
13062 /*
13063  *  Table for hex encoding bytes
13064  */
13065 
13066 #if defined(DUK_USE_HEX_FASTPATH)
13067 /* Lookup to encode one byte directly into 2 characters:
13068  *
13069  *   def genhextab(bswap):
13070  *       for i in xrange(256):
13071  *           t = chr(i).encode('hex')
13072  *           if bswap:
13073  *               t = t[1] + t[0]
13074  *           print('0x' + t.encode('hex') + 'U')
13075  *   print('big endian'); genhextab(False)
13076  *   print('little endian'); genhextab(True)
13077 */
13078 DUK_INTERNAL const duk_uint16_t duk_hex_enctab[256] = {
13079 #if defined(DUK_USE_INTEGER_BE)
13080 	0x3030U, 0x3031U, 0x3032U, 0x3033U, 0x3034U, 0x3035U, 0x3036U, 0x3037U,
13081 	0x3038U, 0x3039U, 0x3061U, 0x3062U, 0x3063U, 0x3064U, 0x3065U, 0x3066U,
13082 	0x3130U, 0x3131U, 0x3132U, 0x3133U, 0x3134U, 0x3135U, 0x3136U, 0x3137U,
13083 	0x3138U, 0x3139U, 0x3161U, 0x3162U, 0x3163U, 0x3164U, 0x3165U, 0x3166U,
13084 	0x3230U, 0x3231U, 0x3232U, 0x3233U, 0x3234U, 0x3235U, 0x3236U, 0x3237U,
13085 	0x3238U, 0x3239U, 0x3261U, 0x3262U, 0x3263U, 0x3264U, 0x3265U, 0x3266U,
13086 	0x3330U, 0x3331U, 0x3332U, 0x3333U, 0x3334U, 0x3335U, 0x3336U, 0x3337U,
13087 	0x3338U, 0x3339U, 0x3361U, 0x3362U, 0x3363U, 0x3364U, 0x3365U, 0x3366U,
13088 	0x3430U, 0x3431U, 0x3432U, 0x3433U, 0x3434U, 0x3435U, 0x3436U, 0x3437U,
13089 	0x3438U, 0x3439U, 0x3461U, 0x3462U, 0x3463U, 0x3464U, 0x3465U, 0x3466U,
13090 	0x3530U, 0x3531U, 0x3532U, 0x3533U, 0x3534U, 0x3535U, 0x3536U, 0x3537U,
13091 	0x3538U, 0x3539U, 0x3561U, 0x3562U, 0x3563U, 0x3564U, 0x3565U, 0x3566U,
13092 	0x3630U, 0x3631U, 0x3632U, 0x3633U, 0x3634U, 0x3635U, 0x3636U, 0x3637U,
13093 	0x3638U, 0x3639U, 0x3661U, 0x3662U, 0x3663U, 0x3664U, 0x3665U, 0x3666U,
13094 	0x3730U, 0x3731U, 0x3732U, 0x3733U, 0x3734U, 0x3735U, 0x3736U, 0x3737U,
13095 	0x3738U, 0x3739U, 0x3761U, 0x3762U, 0x3763U, 0x3764U, 0x3765U, 0x3766U,
13096 	0x3830U, 0x3831U, 0x3832U, 0x3833U, 0x3834U, 0x3835U, 0x3836U, 0x3837U,
13097 	0x3838U, 0x3839U, 0x3861U, 0x3862U, 0x3863U, 0x3864U, 0x3865U, 0x3866U,
13098 	0x3930U, 0x3931U, 0x3932U, 0x3933U, 0x3934U, 0x3935U, 0x3936U, 0x3937U,
13099 	0x3938U, 0x3939U, 0x3961U, 0x3962U, 0x3963U, 0x3964U, 0x3965U, 0x3966U,
13100 	0x6130U, 0x6131U, 0x6132U, 0x6133U, 0x6134U, 0x6135U, 0x6136U, 0x6137U,
13101 	0x6138U, 0x6139U, 0x6161U, 0x6162U, 0x6163U, 0x6164U, 0x6165U, 0x6166U,
13102 	0x6230U, 0x6231U, 0x6232U, 0x6233U, 0x6234U, 0x6235U, 0x6236U, 0x6237U,
13103 	0x6238U, 0x6239U, 0x6261U, 0x6262U, 0x6263U, 0x6264U, 0x6265U, 0x6266U,
13104 	0x6330U, 0x6331U, 0x6332U, 0x6333U, 0x6334U, 0x6335U, 0x6336U, 0x6337U,
13105 	0x6338U, 0x6339U, 0x6361U, 0x6362U, 0x6363U, 0x6364U, 0x6365U, 0x6366U,
13106 	0x6430U, 0x6431U, 0x6432U, 0x6433U, 0x6434U, 0x6435U, 0x6436U, 0x6437U,
13107 	0x6438U, 0x6439U, 0x6461U, 0x6462U, 0x6463U, 0x6464U, 0x6465U, 0x6466U,
13108 	0x6530U, 0x6531U, 0x6532U, 0x6533U, 0x6534U, 0x6535U, 0x6536U, 0x6537U,
13109 	0x6538U, 0x6539U, 0x6561U, 0x6562U, 0x6563U, 0x6564U, 0x6565U, 0x6566U,
13110 	0x6630U, 0x6631U, 0x6632U, 0x6633U, 0x6634U, 0x6635U, 0x6636U, 0x6637U,
13111 	0x6638U, 0x6639U, 0x6661U, 0x6662U, 0x6663U, 0x6664U, 0x6665U, 0x6666U
13112 #else  /* DUK_USE_INTEGER_BE */
13113 	0x3030U, 0x3130U, 0x3230U, 0x3330U, 0x3430U, 0x3530U, 0x3630U, 0x3730U,
13114 	0x3830U, 0x3930U, 0x6130U, 0x6230U, 0x6330U, 0x6430U, 0x6530U, 0x6630U,
13115 	0x3031U, 0x3131U, 0x3231U, 0x3331U, 0x3431U, 0x3531U, 0x3631U, 0x3731U,
13116 	0x3831U, 0x3931U, 0x6131U, 0x6231U, 0x6331U, 0x6431U, 0x6531U, 0x6631U,
13117 	0x3032U, 0x3132U, 0x3232U, 0x3332U, 0x3432U, 0x3532U, 0x3632U, 0x3732U,
13118 	0x3832U, 0x3932U, 0x6132U, 0x6232U, 0x6332U, 0x6432U, 0x6532U, 0x6632U,
13119 	0x3033U, 0x3133U, 0x3233U, 0x3333U, 0x3433U, 0x3533U, 0x3633U, 0x3733U,
13120 	0x3833U, 0x3933U, 0x6133U, 0x6233U, 0x6333U, 0x6433U, 0x6533U, 0x6633U,
13121 	0x3034U, 0x3134U, 0x3234U, 0x3334U, 0x3434U, 0x3534U, 0x3634U, 0x3734U,
13122 	0x3834U, 0x3934U, 0x6134U, 0x6234U, 0x6334U, 0x6434U, 0x6534U, 0x6634U,
13123 	0x3035U, 0x3135U, 0x3235U, 0x3335U, 0x3435U, 0x3535U, 0x3635U, 0x3735U,
13124 	0x3835U, 0x3935U, 0x6135U, 0x6235U, 0x6335U, 0x6435U, 0x6535U, 0x6635U,
13125 	0x3036U, 0x3136U, 0x3236U, 0x3336U, 0x3436U, 0x3536U, 0x3636U, 0x3736U,
13126 	0x3836U, 0x3936U, 0x6136U, 0x6236U, 0x6336U, 0x6436U, 0x6536U, 0x6636U,
13127 	0x3037U, 0x3137U, 0x3237U, 0x3337U, 0x3437U, 0x3537U, 0x3637U, 0x3737U,
13128 	0x3837U, 0x3937U, 0x6137U, 0x6237U, 0x6337U, 0x6437U, 0x6537U, 0x6637U,
13129 	0x3038U, 0x3138U, 0x3238U, 0x3338U, 0x3438U, 0x3538U, 0x3638U, 0x3738U,
13130 	0x3838U, 0x3938U, 0x6138U, 0x6238U, 0x6338U, 0x6438U, 0x6538U, 0x6638U,
13131 	0x3039U, 0x3139U, 0x3239U, 0x3339U, 0x3439U, 0x3539U, 0x3639U, 0x3739U,
13132 	0x3839U, 0x3939U, 0x6139U, 0x6239U, 0x6339U, 0x6439U, 0x6539U, 0x6639U,
13133 	0x3061U, 0x3161U, 0x3261U, 0x3361U, 0x3461U, 0x3561U, 0x3661U, 0x3761U,
13134 	0x3861U, 0x3961U, 0x6161U, 0x6261U, 0x6361U, 0x6461U, 0x6561U, 0x6661U,
13135 	0x3062U, 0x3162U, 0x3262U, 0x3362U, 0x3462U, 0x3562U, 0x3662U, 0x3762U,
13136 	0x3862U, 0x3962U, 0x6162U, 0x6262U, 0x6362U, 0x6462U, 0x6562U, 0x6662U,
13137 	0x3063U, 0x3163U, 0x3263U, 0x3363U, 0x3463U, 0x3563U, 0x3663U, 0x3763U,
13138 	0x3863U, 0x3963U, 0x6163U, 0x6263U, 0x6363U, 0x6463U, 0x6563U, 0x6663U,
13139 	0x3064U, 0x3164U, 0x3264U, 0x3364U, 0x3464U, 0x3564U, 0x3664U, 0x3764U,
13140 	0x3864U, 0x3964U, 0x6164U, 0x6264U, 0x6364U, 0x6464U, 0x6564U, 0x6664U,
13141 	0x3065U, 0x3165U, 0x3265U, 0x3365U, 0x3465U, 0x3565U, 0x3665U, 0x3765U,
13142 	0x3865U, 0x3965U, 0x6165U, 0x6265U, 0x6365U, 0x6465U, 0x6565U, 0x6665U,
13143 	0x3066U, 0x3166U, 0x3266U, 0x3366U, 0x3466U, 0x3566U, 0x3666U, 0x3766U,
13144 	0x3866U, 0x3966U, 0x6166U, 0x6266U, 0x6366U, 0x6466U, 0x6566U, 0x6666U
13145 #endif  /* DUK_USE_INTEGER_BE */
13146 };
13147 #endif  /* DUK_USE_HEX_FASTPATH */
13148 
13149 /*
13150  *  Arbitrary byteswap for potentially unaligned values
13151  *
13152  *  Used to byteswap pointers e.g. in debugger code.
13153  */
13154 
13155 #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)13156 DUK_INTERNAL void duk_byteswap_bytes(duk_uint8_t *p, duk_small_uint_t len) {
13157 	duk_uint8_t tmp;
13158 	duk_uint8_t *q = p + len - 1;
13159 
13160 	while (p - q < 0) {
13161 		tmp = *p;
13162 		*p = *q;
13163 		*q = tmp;
13164 		p++;
13165 		q--;
13166 	}
13167 }
13168 #endif
13169 #line 1 "duk_hobject_class.c"
13170 /*
13171  *  Hobject ECMAScript [[Class]].
13172  */
13173 
13174 /* #include duk_internal.h -> already included */
13175 
13176 #if (DUK_STRIDX_UC_ARGUMENTS > 255)
13177 #error constant too large
13178 #endif
13179 #if (DUK_STRIDX_ARRAY > 255)
13180 #error constant too large
13181 #endif
13182 #if (DUK_STRIDX_UC_BOOLEAN > 255)
13183 #error constant too large
13184 #endif
13185 #if (DUK_STRIDX_DATE > 255)
13186 #error constant too large
13187 #endif
13188 #if (DUK_STRIDX_UC_ERROR > 255)
13189 #error constant too large
13190 #endif
13191 #if (DUK_STRIDX_UC_FUNCTION > 255)
13192 #error constant too large
13193 #endif
13194 #if (DUK_STRIDX_JSON > 255)
13195 #error constant too large
13196 #endif
13197 #if (DUK_STRIDX_MATH > 255)
13198 #error constant too large
13199 #endif
13200 #if (DUK_STRIDX_UC_NUMBER > 255)
13201 #error constant too large
13202 #endif
13203 #if (DUK_STRIDX_UC_OBJECT > 255)
13204 #error constant too large
13205 #endif
13206 #if (DUK_STRIDX_REG_EXP > 255)
13207 #error constant too large
13208 #endif
13209 #if (DUK_STRIDX_UC_STRING > 255)
13210 #error constant too large
13211 #endif
13212 #if (DUK_STRIDX_GLOBAL > 255)
13213 #error constant too large
13214 #endif
13215 #if (DUK_STRIDX_OBJ_ENV > 255)
13216 #error constant too large
13217 #endif
13218 #if (DUK_STRIDX_DEC_ENV > 255)
13219 #error constant too large
13220 #endif
13221 #if (DUK_STRIDX_UC_POINTER > 255)
13222 #error constant too large
13223 #endif
13224 #if (DUK_STRIDX_UC_THREAD > 255)
13225 #error constant too large
13226 #endif
13227 #if (DUK_STRIDX_ARRAY_BUFFER > 255)
13228 #error constant too large
13229 #endif
13230 #if (DUK_STRIDX_DATA_VIEW > 255)
13231 #error constant too large
13232 #endif
13233 #if (DUK_STRIDX_INT8_ARRAY > 255)
13234 #error constant too large
13235 #endif
13236 #if (DUK_STRIDX_UINT8_ARRAY > 255)
13237 #error constant too large
13238 #endif
13239 #if (DUK_STRIDX_UINT8_CLAMPED_ARRAY > 255)
13240 #error constant too large
13241 #endif
13242 #if (DUK_STRIDX_INT16_ARRAY > 255)
13243 #error constant too large
13244 #endif
13245 #if (DUK_STRIDX_UINT16_ARRAY > 255)
13246 #error constant too large
13247 #endif
13248 #if (DUK_STRIDX_INT32_ARRAY > 255)
13249 #error constant too large
13250 #endif
13251 #if (DUK_STRIDX_UINT32_ARRAY > 255)
13252 #error constant too large
13253 #endif
13254 #if (DUK_STRIDX_FLOAT32_ARRAY > 255)
13255 #error constant too large
13256 #endif
13257 #if (DUK_STRIDX_FLOAT64_ARRAY > 255)
13258 #error constant too large
13259 #endif
13260 #if (DUK_STRIDX_EMPTY_STRING > 255)
13261 #error constant too large
13262 #endif
13263 
13264 /* Note: assumes that these string indexes are 8-bit, genstrings.py must ensure that */
13265 DUK_INTERNAL duk_uint8_t duk_class_number_to_stridx[32] = {
13266 	DUK_STRIDX_EMPTY_STRING,  /* NONE, intentionally empty */
13267 	DUK_STRIDX_UC_OBJECT,
13268 	DUK_STRIDX_ARRAY,
13269 	DUK_STRIDX_UC_FUNCTION,
13270 	DUK_STRIDX_UC_ARGUMENTS,
13271 	DUK_STRIDX_UC_BOOLEAN,
13272 	DUK_STRIDX_DATE,
13273 	DUK_STRIDX_UC_ERROR,
13274 	DUK_STRIDX_JSON,
13275 	DUK_STRIDX_MATH,
13276 	DUK_STRIDX_UC_NUMBER,
13277 	DUK_STRIDX_REG_EXP,
13278 	DUK_STRIDX_UC_STRING,
13279 	DUK_STRIDX_GLOBAL,
13280 	DUK_STRIDX_UC_SYMBOL,
13281 	DUK_STRIDX_OBJ_ENV,
13282 	DUK_STRIDX_DEC_ENV,
13283 	DUK_STRIDX_UC_POINTER,
13284 	DUK_STRIDX_UC_THREAD,
13285 	DUK_STRIDX_ARRAY_BUFFER,
13286 	DUK_STRIDX_DATA_VIEW,
13287 	DUK_STRIDX_INT8_ARRAY,
13288 	DUK_STRIDX_UINT8_ARRAY,
13289 	DUK_STRIDX_UINT8_CLAMPED_ARRAY,
13290 	DUK_STRIDX_INT16_ARRAY,
13291 	DUK_STRIDX_UINT16_ARRAY,
13292 	DUK_STRIDX_INT32_ARRAY,
13293 	DUK_STRIDX_UINT32_ARRAY,
13294 	DUK_STRIDX_FLOAT32_ARRAY,
13295 	DUK_STRIDX_FLOAT64_ARRAY,
13296 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13297 	DUK_STRIDX_EMPTY_STRING,  /* UNUSED, intentionally empty */
13298 };
13299 #line 1 "duk_alloc_default.c"
13300 /*
13301  *  Default allocation functions.
13302  *
13303  *  Assumes behavior such as malloc allowing zero size, yielding
13304  *  a NULL or a unique pointer which is a no-op for free.
13305  */
13306 
13307 /* #include duk_internal.h -> already included */
13308 
13309 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
duk_default_alloc_function(void * udata,duk_size_t size)13310 DUK_INTERNAL void *duk_default_alloc_function(void *udata, duk_size_t size) {
13311 	void *res;
13312 	DUK_UNREF(udata);
13313 	res = DUK_ANSI_MALLOC(size);
13314 	DUK_DDD(DUK_DDDPRINT("default alloc function: %lu -> %p",
13315 	                     (unsigned long) size, (void *) res));
13316 	return res;
13317 }
13318 
duk_default_realloc_function(void * udata,void * ptr,duk_size_t newsize)13319 DUK_INTERNAL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize) {
13320 	void *res;
13321 	DUK_UNREF(udata);
13322 	res = DUK_ANSI_REALLOC(ptr, newsize);
13323 	DUK_DDD(DUK_DDDPRINT("default realloc function: %p %lu -> %p",
13324 	                     (void *) ptr, (unsigned long) newsize, (void *) res));
13325 	return res;
13326 }
13327 
duk_default_free_function(void * udata,void * ptr)13328 DUK_INTERNAL void duk_default_free_function(void *udata, void *ptr) {
13329 	DUK_DDD(DUK_DDDPRINT("default free function: %p", (void *) ptr));
13330 	DUK_UNREF(udata);
13331 	DUK_ANSI_FREE(ptr);
13332 }
13333 #endif  /* DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS */
13334 #line 1 "duk_api_buffer.c"
13335 /*
13336  *  Buffer
13337  */
13338 
13339 /* #include duk_internal.h -> already included */
13340 
duk_resize_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t new_size)13341 DUK_EXTERNAL void *duk_resize_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t new_size) {
13342 	duk_hbuffer_dynamic *h;
13343 
13344 	DUK_ASSERT_API_ENTRY(thr);
13345 
13346 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13347 	DUK_ASSERT(h != NULL);
13348 
13349 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13350 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13351 		DUK_WO_NORETURN(return NULL;);
13352 	}
13353 
13354 	/* Maximum size check is handled by callee. */
13355 	duk_hbuffer_resize(thr, h, new_size);
13356 
13357 	return DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13358 }
13359 
duk_steal_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)13360 DUK_EXTERNAL void *duk_steal_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
13361 	duk_hbuffer_dynamic *h;
13362 	void *ptr;
13363 	duk_size_t sz;
13364 
13365 	DUK_ASSERT_API_ENTRY(thr);
13366 
13367 	h = (duk_hbuffer_dynamic *) duk_require_hbuffer(thr, idx);
13368 	DUK_ASSERT(h != NULL);
13369 
13370 	if (!(DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h))) {
13371 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13372 		DUK_WO_NORETURN(return NULL;);
13373 	}
13374 
13375 	/* Forget the previous allocation, setting size to 0 and alloc to
13376 	 * NULL.  Caller is responsible for freeing the previous allocation.
13377 	 * Getting the allocation and clearing it is done in the same API
13378 	 * call to avoid any chance of a realloc.
13379 	 */
13380 	ptr = DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h);
13381 	sz = DUK_HBUFFER_DYNAMIC_GET_SIZE(h);
13382 	if (out_size) {
13383 		*out_size = sz;
13384 	}
13385 	DUK_HBUFFER_DYNAMIC_SET_DATA_PTR_NULL(thr->heap, h);
13386 	DUK_HBUFFER_DYNAMIC_SET_SIZE(h, 0);
13387 
13388 	return ptr;
13389 }
13390 
duk_config_buffer(duk_hthread * thr,duk_idx_t idx,void * ptr,duk_size_t len)13391 DUK_EXTERNAL void duk_config_buffer(duk_hthread *thr, duk_idx_t idx, void *ptr, duk_size_t len) {
13392 	duk_hbuffer_external *h;
13393 
13394 	DUK_ASSERT_API_ENTRY(thr);
13395 
13396 	h = (duk_hbuffer_external *) duk_require_hbuffer(thr, idx);
13397 	DUK_ASSERT(h != NULL);
13398 
13399 	if (!DUK_HBUFFER_HAS_EXTERNAL(h)) {
13400 		DUK_ERROR_TYPE(thr, DUK_STR_WRONG_BUFFER_TYPE);
13401 		DUK_WO_NORETURN(return;);
13402 	}
13403 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h));
13404 
13405 	DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(thr->heap, h, ptr);
13406 	DUK_HBUFFER_EXTERNAL_SET_SIZE(h, len);
13407 }
13408 #line 1 "duk_api_bytecode.c"
13409 /*
13410  *  Bytecode dump/load
13411  *
13412  *  The bytecode load primitive is more important performance-wise than the
13413  *  dump primitive.
13414  *
13415  *  Unlike most Duktape API calls, bytecode dump/load is not guaranteed to be
13416  *  memory safe for invalid arguments - caller beware!  There's little point
13417  *  in trying to achieve memory safety unless bytecode instructions are also
13418  *  validated which is not easy to do with indirect register references etc.
13419  */
13420 
13421 /* #include duk_internal.h -> already included */
13422 
13423 #if defined(DUK_USE_BYTECODE_DUMP_SUPPORT)
13424 
13425 #define DUK__SER_MARKER  0xbf
13426 #define DUK__SER_STRING  0x00
13427 #define DUK__SER_NUMBER  0x01
13428 #define DUK__BYTECODE_INITIAL_ALLOC 256
13429 #define DUK__NO_FORMALS  0xffffffffUL
13430 
13431 /*
13432  *  Dump/load helpers, xxx_raw() helpers do no buffer checks
13433  */
13434 
duk__load_string_raw(duk_hthread * thr,duk_uint8_t * p)13435 DUK_LOCAL duk_uint8_t *duk__load_string_raw(duk_hthread *thr, duk_uint8_t *p) {
13436 	duk_uint32_t len;
13437 
13438 	len = DUK_RAW_READ_U32_BE(p);
13439 	duk_push_lstring(thr, (const char *) p, len);
13440 	p += len;
13441 	return p;
13442 }
13443 
duk__load_buffer_raw(duk_hthread * thr,duk_uint8_t * p)13444 DUK_LOCAL duk_uint8_t *duk__load_buffer_raw(duk_hthread *thr, duk_uint8_t *p) {
13445 	duk_uint32_t len;
13446 	duk_uint8_t *buf;
13447 
13448 	len = DUK_RAW_READ_U32_BE(p);
13449 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);
13450 	DUK_ASSERT(buf != NULL);
13451 	duk_memcpy((void *) buf, (const void *) p, (size_t) len);
13452 	p += len;
13453 	return p;
13454 }
13455 
duk__dump_hstring_raw(duk_uint8_t * p,duk_hstring * h)13456 DUK_LOCAL duk_uint8_t *duk__dump_hstring_raw(duk_uint8_t *p, duk_hstring *h) {
13457 	duk_size_t len;
13458 	duk_uint32_t tmp32;
13459 
13460 	DUK_ASSERT(h != NULL);
13461 
13462 	len = DUK_HSTRING_GET_BYTELEN(h);
13463 	DUK_ASSERT(len <= 0xffffffffUL);  /* string limits */
13464 	tmp32 = (duk_uint32_t) len;
13465 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13466 	duk_memcpy((void *) p,
13467 	           (const void *) DUK_HSTRING_GET_DATA(h),
13468 	           len);
13469 	p += len;
13470 	return p;
13471 }
13472 
duk__dump_hbuffer_raw(duk_hthread * thr,duk_uint8_t * p,duk_hbuffer * h)13473 DUK_LOCAL duk_uint8_t *duk__dump_hbuffer_raw(duk_hthread *thr, duk_uint8_t *p, duk_hbuffer *h) {
13474 	duk_size_t len;
13475 	duk_uint32_t tmp32;
13476 
13477 	DUK_ASSERT(thr != NULL);
13478 	DUK_ASSERT(h != NULL);
13479 	DUK_UNREF(thr);
13480 
13481 	len = DUK_HBUFFER_GET_SIZE(h);
13482 	DUK_ASSERT(len <= 0xffffffffUL);  /* buffer limits */
13483 	tmp32 = (duk_uint32_t) len;
13484 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13485 	/* When len == 0, buffer data pointer may be NULL. */
13486 	duk_memcpy_unsafe((void *) p,
13487 	                  (const void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h),
13488 	                  len);
13489 	p += len;
13490 	return p;
13491 }
13492 
duk__dump_string_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13493 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) {
13494 	duk_hstring *h_str;
13495 	duk_tval *tv;
13496 
13497 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13498 	if (tv != NULL && DUK_TVAL_IS_STRING(tv)) {
13499 		h_str = DUK_TVAL_GET_STRING(tv);
13500 		DUK_ASSERT(h_str != NULL);
13501 	} else {
13502 		h_str = DUK_HTHREAD_STRING_EMPTY_STRING(thr);
13503 		DUK_ASSERT(h_str != NULL);
13504 	}
13505 	DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13506 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13507 	p = duk__dump_hstring_raw(p, h_str);
13508 	return p;
13509 }
13510 
duk__dump_buffer_prop(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func,duk_small_uint_t stridx)13511 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) {
13512 	duk_tval *tv;
13513 
13514 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13515 	if (tv != NULL && DUK_TVAL_IS_BUFFER(tv)) {
13516 		duk_hbuffer *h_buf;
13517 		h_buf = DUK_TVAL_GET_BUFFER(tv);
13518 		DUK_ASSERT(h_buf != NULL);
13519 		DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13520 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HBUFFER_GET_SIZE(h_buf), p);
13521 		p = duk__dump_hbuffer_raw(thr, p, h_buf);
13522 	} else {
13523 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13524 		DUK_RAW_WRITE_U32_BE(p, 0);
13525 	}
13526 	return p;
13527 }
13528 
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)13529 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) {
13530 	duk_tval *tv;
13531 	duk_uint32_t val;
13532 
13533 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_GET_STRING(thr, stridx));
13534 	if (tv != NULL && DUK_TVAL_IS_NUMBER(tv)) {
13535 		val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv);
13536 	} else {
13537 		val = def_value;
13538 	}
13539 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13540 	DUK_RAW_WRITE_U32_BE(p, val);
13541 	return p;
13542 }
13543 
duk__dump_varmap(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13544 DUK_LOCAL duk_uint8_t *duk__dump_varmap(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13545 	duk_tval *tv;
13546 
13547 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
13548 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
13549 		duk_hobject *h;
13550 		duk_uint_fast32_t i;
13551 
13552 		h = DUK_TVAL_GET_OBJECT(tv);
13553 		DUK_ASSERT(h != NULL);
13554 
13555 		/* We know _Varmap only has own properties so walk property
13556 		 * table directly.  We also know _Varmap is dense and all
13557 		 * values are numbers; assert for these.  GC and finalizers
13558 		 * shouldn't affect _Varmap so side effects should be fine.
13559 		 */
13560 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
13561 			duk_hstring *key;
13562 			duk_tval *tv_val;
13563 			duk_uint32_t val;
13564 
13565 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, h, i);
13566 			DUK_ASSERT(key != NULL);  /* _Varmap is dense */
13567 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h, i));
13568 			tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h, i);
13569 			DUK_ASSERT(tv_val != NULL);
13570 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_val));  /* known to be number; in fact an integer */
13571 #if defined(DUK_USE_FASTINT)
13572 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_val));
13573 			DUK_ASSERT(DUK_TVAL_GET_FASTINT(tv_val) == (duk_int64_t) DUK_TVAL_GET_FASTINT_U32(tv_val));  /* known to be 32-bit */
13574 			val = DUK_TVAL_GET_FASTINT_U32(tv_val);
13575 #else
13576 			val = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv_val);
13577 #endif
13578 
13579 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13580 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(key) + 4U, p);
13581 			p = duk__dump_hstring_raw(p, key);
13582 			DUK_RAW_WRITE_U32_BE(p, val);
13583 		}
13584 	}
13585 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13586 	DUK_RAW_WRITE_U32_BE(p, 0);  /* end of _Varmap */
13587 	return p;
13588 }
13589 
duk__dump_formals(duk_hthread * thr,duk_uint8_t * p,duk_bufwriter_ctx * bw_ctx,duk_hobject * func)13590 DUK_LOCAL duk_uint8_t *duk__dump_formals(duk_hthread *thr, duk_uint8_t *p, duk_bufwriter_ctx *bw_ctx, duk_hobject *func) {
13591 	duk_tval *tv;
13592 
13593 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) func, DUK_HTHREAD_STRING_INT_FORMALS(thr));
13594 	if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
13595 		duk_harray *h;
13596 		duk_uint32_t i;
13597 
13598 		/* Here we rely on _Formals being a dense array containing
13599 		 * strings.  This should be the case unless _Formals has been
13600 		 * tweaked by the application (which we don't support right
13601 		 * now).
13602 		 */
13603 		h = (duk_harray *) DUK_TVAL_GET_OBJECT(tv);
13604 		DUK_ASSERT(h != NULL);
13605 		DUK_ASSERT(DUK_HOBJECT_IS_ARRAY((duk_hobject *) h));
13606 		DUK_ASSERT(h->length <= DUK_HOBJECT_GET_ASIZE((duk_hobject *) h));
13607 
13608 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13609 		DUK_ASSERT(h->length != DUK__NO_FORMALS);  /* limits */
13610 		DUK_RAW_WRITE_U32_BE(p, h->length);
13611 
13612 		for (i = 0; i < h->length; i++) {
13613 			duk_tval *tv_val;
13614 			duk_hstring *varname;
13615 
13616 			tv_val = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, (duk_hobject *) h, i);
13617 			DUK_ASSERT(tv_val != NULL);
13618 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_val));
13619 
13620 			varname = DUK_TVAL_GET_STRING(tv_val);
13621 			DUK_ASSERT(varname != NULL);
13622 			DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(varname) >= 1);
13623 
13624 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13625 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U + DUK_HSTRING_GET_BYTELEN(varname), p);
13626 			p = duk__dump_hstring_raw(p, varname);
13627 		}
13628 	} else {
13629 		DUK_DD(DUK_DDPRINT("dumping function without _Formals, emit marker to indicate missing _Formals"));
13630 		p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 4U, p);
13631 		DUK_RAW_WRITE_U32_BE(p, DUK__NO_FORMALS);  /* marker: no formals */
13632 	}
13633 	return p;
13634 }
13635 
duk__dump_func(duk_hthread * thr,duk_hcompfunc * func,duk_bufwriter_ctx * bw_ctx,duk_uint8_t * p)13636 static duk_uint8_t *duk__dump_func(duk_hthread *thr, duk_hcompfunc *func, duk_bufwriter_ctx *bw_ctx, duk_uint8_t *p) {
13637 	duk_tval *tv, *tv_end;
13638 	duk_instr_t *ins, *ins_end;
13639 	duk_hobject **fn, **fn_end;
13640 	duk_hstring *h_str;
13641 	duk_uint32_t count_instr;
13642 	duk_uint32_t tmp32;
13643 	duk_uint16_t tmp16;
13644 	duk_double_t d;
13645 
13646 	DUK_DD(DUK_DDPRINT("dumping function %p to %p: "
13647 	                   "consts=[%p,%p[ (%ld bytes, %ld items), "
13648 	                   "funcs=[%p,%p[ (%ld bytes, %ld items), "
13649 	                   "code=[%p,%p[ (%ld bytes, %ld items)",
13650 	                   (void *) func,
13651 	                   (void *) p,
13652 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func),
13653 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func),
13654 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_SIZE(thr->heap, func),
13655 	                   (long) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func),
13656 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func),
13657 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func),
13658 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_SIZE(thr->heap, func),
13659 	                   (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func),
13660 	                   (void *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func),
13661 	                   (void *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func),
13662 	                   (long) DUK_HCOMPFUNC_GET_CODE_SIZE(thr->heap, func),
13663 	                   (long) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func)));
13664 
13665 	DUK_ASSERT(DUK_USE_ESBC_MAX_BYTES <= 0x7fffffffUL);  /* ensures no overflow */
13666 	count_instr = (duk_uint32_t) DUK_HCOMPFUNC_GET_CODE_COUNT(thr->heap, func);
13667 	p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 3U * 4U + 2U * 2U + 3U * 4U + count_instr * 4U, p);
13668 
13669 	/* Fixed header info. */
13670 	tmp32 = count_instr;
13671 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13672 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_CONSTS_COUNT(thr->heap, func);
13673 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13674 	tmp32 = (duk_uint32_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, func);
13675 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13676 	tmp16 = func->nregs;
13677 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13678 	tmp16 = func->nargs;
13679 	DUK_RAW_WRITE_U16_BE(p, tmp16);
13680 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13681 	tmp32 = func->start_line;
13682 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13683 	tmp32 = func->end_line;
13684 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13685 #else
13686 	DUK_RAW_WRITE_U32_BE(p, 0);
13687 	DUK_RAW_WRITE_U32_BE(p, 0);
13688 #endif
13689 	tmp32 = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) func);  /* masks flags, only duk_hobject flags */
13690 	tmp32 &= ~(DUK_HOBJECT_FLAG_HAVE_FINALIZER);  /* finalizer flag is lost */
13691 	DUK_RAW_WRITE_U32_BE(p, tmp32);
13692 
13693 	/* Bytecode instructions: endian conversion needed unless
13694 	 * platform is big endian.
13695 	 */
13696 	ins = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, func);
13697 	ins_end = DUK_HCOMPFUNC_GET_CODE_END(thr->heap, func);
13698 	DUK_ASSERT((duk_size_t) (ins_end - ins) == (duk_size_t) count_instr);
13699 #if defined(DUK_USE_INTEGER_BE)
13700 	duk_memcpy_unsafe((void *) p, (const void *) ins, (size_t) (ins_end - ins));
13701 	p += (size_t) (ins_end - ins);
13702 #else
13703 	while (ins != ins_end) {
13704 		tmp32 = (duk_uint32_t) (*ins);
13705 		DUK_RAW_WRITE_U32_BE(p, tmp32);
13706 		ins++;
13707 	}
13708 #endif
13709 
13710 	/* Constants: variable size encoding. */
13711 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, func);
13712 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, func);
13713 	while (tv != tv_end) {
13714 		/* constants are strings or numbers now */
13715 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv) ||
13716 		           DUK_TVAL_IS_NUMBER(tv));
13717 
13718 		if (DUK_TVAL_IS_STRING(tv)) {
13719 			h_str = DUK_TVAL_GET_STRING(tv);
13720 			DUK_ASSERT(h_str != NULL);
13721 			DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= 0x7fffffffUL);  /* ensures no overflow */
13722 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 4U + DUK_HSTRING_GET_BYTELEN(h_str), p);
13723 			*p++ = DUK__SER_STRING;
13724 			p = duk__dump_hstring_raw(p, h_str);
13725 		} else {
13726 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
13727 			p = DUK_BW_ENSURE_RAW(thr, bw_ctx, 1U + 8U, p);
13728 			*p++ = DUK__SER_NUMBER;
13729 			d = DUK_TVAL_GET_NUMBER(tv);
13730 			DUK_RAW_WRITE_DOUBLE_BE(p, d);
13731 		}
13732 		tv++;
13733 	}
13734 
13735 	/* Inner functions recursively. */
13736 	fn = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, func);
13737 	fn_end = (duk_hobject **) DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, func);
13738 	while (fn != fn_end) {
13739 		/* XXX: This causes recursion up to inner function depth
13740 		 * which is normally not an issue, e.g. mark-and-sweep uses
13741 		 * a recursion limiter to avoid C stack issues.  Avoiding
13742 		 * this would mean some sort of a work list or just refusing
13743 		 * to serialize deep functions.
13744 		 */
13745 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(*fn));
13746 		p = duk__dump_func(thr, (duk_hcompfunc *) *fn, bw_ctx, p);
13747 		fn++;
13748 	}
13749 
13750 	/* Lexenv and varenv are not dumped. */
13751 
13752 	/* Object extra properties.
13753 	 *
13754 	 * There are some difference between function templates and functions.
13755 	 * For example, function templates don't have .length and nargs is
13756 	 * normally used to instantiate the functions.
13757 	 */
13758 
13759 	p = duk__dump_uint32_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_LENGTH, (duk_uint32_t) func->nargs);
13760 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13761 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_NAME);
13762 #endif
13763 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
13764 	p = duk__dump_string_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_FILE_NAME);
13765 #endif
13766 #if defined(DUK_USE_PC2LINE)
13767 	p = duk__dump_buffer_prop(thr, p, bw_ctx, (duk_hobject *) func, DUK_STRIDX_INT_PC2LINE);
13768 #endif
13769 	p = duk__dump_varmap(thr, p, bw_ctx, (duk_hobject *) func);
13770 	p = duk__dump_formals(thr, p, bw_ctx, (duk_hobject *) func);
13771 
13772 	DUK_DD(DUK_DDPRINT("serialized function %p -> final pointer %p", (void *) func, (void *) p));
13773 
13774 	return p;
13775 }
13776 
13777 /* Load a function from bytecode.  The function object returned here must
13778  * match what is created by duk_js_push_closure() with respect to its flags,
13779  * properties, etc.
13780  *
13781  * NOTE: there are intentionally no input buffer length / bound checks.
13782  * Adding them would be easy but wouldn't ensure memory safety as untrusted
13783  * or broken bytecode is unsafe during execution unless the opcodes themselves
13784  * are validated (which is quite complex, especially for indirect opcodes).
13785  */
13786 
13787 #define DUK__ASSERT_LEFT(n) do { \
13788 		DUK_ASSERT((duk_size_t) (p_end - p) >= (duk_size_t) (n)); \
13789 	} while (0)
13790 
duk__load_func(duk_hthread * thr,duk_uint8_t * p,duk_uint8_t * p_end)13791 static duk_uint8_t *duk__load_func(duk_hthread *thr, duk_uint8_t *p, duk_uint8_t *p_end) {
13792 	duk_hcompfunc *h_fun;
13793 	duk_hbuffer *h_data;
13794 	duk_size_t data_size;
13795 	duk_uint32_t count_instr, count_const, count_funcs;
13796 	duk_uint32_t n;
13797 	duk_uint32_t tmp32;
13798 	duk_small_uint_t const_type;
13799 	duk_uint8_t *fun_data;
13800 	duk_uint8_t *q;
13801 	duk_idx_t idx_base;
13802 	duk_tval *tv1;
13803 	duk_uarridx_t arr_idx;
13804 	duk_uarridx_t arr_limit;
13805 	duk_hobject *func_env;
13806 	duk_bool_t need_pop;
13807 
13808 	/* XXX: There's some overlap with duk_js_closure() here, but
13809 	 * seems difficult to share code.  Ensure that the final function
13810 	 * looks the same as created by duk_js_closure().
13811 	 */
13812 
13813 	DUK_ASSERT(thr != NULL);
13814 
13815 	DUK_DD(DUK_DDPRINT("loading function, p=%p, p_end=%p", (void *) p, (void *) p_end));
13816 
13817 	DUK__ASSERT_LEFT(3 * 4);
13818 	count_instr = DUK_RAW_READ_U32_BE(p);
13819 	count_const = DUK_RAW_READ_U32_BE(p);
13820 	count_funcs = DUK_RAW_READ_U32_BE(p);
13821 
13822 	data_size = sizeof(duk_tval) * count_const +
13823 	            sizeof(duk_hobject *) * count_funcs +
13824 	            sizeof(duk_instr_t) * count_instr;
13825 
13826 	DUK_DD(DUK_DDPRINT("instr=%ld, const=%ld, funcs=%ld, data_size=%ld",
13827 	                   (long) count_instr, (long) count_const,
13828 	                   (long) count_const, (long) data_size));
13829 
13830 	/* Value stack is used to ensure reachability of constants and
13831 	 * inner functions being loaded.  Require enough space to handle
13832 	 * large functions correctly.
13833 	 */
13834 	duk_require_stack(thr, (duk_idx_t) (2 + count_const + count_funcs));
13835 	idx_base = duk_get_top(thr);
13836 
13837 	/* Push function object, init flags etc.  This must match
13838 	 * duk_js_push_closure() quite carefully.
13839 	 */
13840 	h_fun = duk_push_hcompfunc(thr);
13841 	DUK_ASSERT(h_fun != NULL);
13842 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) h_fun));
13843 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun) == NULL);
13844 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, h_fun) == NULL);
13845 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, h_fun) == NULL);
13846 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13847 
13848 	h_fun->nregs = DUK_RAW_READ_U16_BE(p);
13849 	h_fun->nargs = DUK_RAW_READ_U16_BE(p);
13850 #if defined(DUK_USE_DEBUGGER_SUPPORT)
13851 	h_fun->start_line = DUK_RAW_READ_U32_BE(p);
13852 	h_fun->end_line = DUK_RAW_READ_U32_BE(p);
13853 #else
13854 	p += 8;  /* skip line info */
13855 #endif
13856 
13857 	/* duk_hcompfunc flags; quite version specific */
13858 	tmp32 = DUK_RAW_READ_U32_BE(p);
13859 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) h_fun, tmp32);  /* masks flags to only change duk_hobject flags */
13860 
13861 	/* standard prototype (no need to set here, already set) */
13862 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_fun) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13863 #if 0
13864 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &h_fun->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
13865 #endif
13866 
13867 	/* assert just a few critical flags */
13868 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h_fun) == DUK_HTYPE_OBJECT);
13869 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&h_fun->obj));
13870 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&h_fun->obj));
13871 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&h_fun->obj));
13872 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&h_fun->obj));
13873 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&h_fun->obj));
13874 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&h_fun->obj));
13875 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&h_fun->obj));
13876 
13877 	/* Create function 'data' buffer but don't attach it yet. */
13878 	fun_data = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, data_size);
13879 	DUK_ASSERT(fun_data != NULL);
13880 
13881 	/* Load bytecode instructions. */
13882 	DUK_ASSERT(sizeof(duk_instr_t) == 4);
13883 	DUK__ASSERT_LEFT(count_instr * sizeof(duk_instr_t));
13884 #if defined(DUK_USE_INTEGER_BE)
13885 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13886 	duk_memcpy((void *) q,
13887 	           (const void *) p,
13888 	           sizeof(duk_instr_t) * count_instr);
13889 	p += sizeof(duk_instr_t) * count_instr;
13890 #else
13891 	q = fun_data + sizeof(duk_tval) * count_const + sizeof(duk_hobject *) * count_funcs;
13892 	for (n = count_instr; n > 0; n--) {
13893 		*((duk_instr_t *) (void *) q) = DUK_RAW_READ_U32_BE(p);
13894 		q += sizeof(duk_instr_t);
13895 	}
13896 #endif
13897 
13898 	/* Load constants onto value stack but don't yet copy to buffer. */
13899 	for (n = count_const; n > 0; n--) {
13900 		DUK__ASSERT_LEFT(1);
13901 		const_type = DUK_RAW_READ_U8(p);
13902 		switch (const_type) {
13903 		case DUK__SER_STRING: {
13904 			p = duk__load_string_raw(thr, p);
13905 			break;
13906 		}
13907 		case DUK__SER_NUMBER: {
13908 			/* Important to do a fastint check so that constants are
13909 			 * properly read back as fastints.
13910 			 */
13911 			duk_tval tv_tmp;
13912 			duk_double_t val;
13913 			DUK__ASSERT_LEFT(8);
13914 			val = DUK_RAW_READ_DOUBLE_BE(p);
13915 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
13916 			duk_push_tval(thr, &tv_tmp);
13917 			break;
13918 		}
13919 		default: {
13920 			goto format_error;
13921 		}
13922 		}
13923 	}
13924 
13925 	/* Load inner functions to value stack, but don't yet copy to buffer. */
13926 	for (n = count_funcs; n > 0; n--) {
13927 		p = duk__load_func(thr, p, p_end);
13928 		if (p == NULL) {
13929 			goto format_error;
13930 		}
13931 	}
13932 
13933 	/* With constants and inner functions on value stack, we can now
13934 	 * atomically finish the function 'data' buffer, bump refcounts,
13935 	 * etc.
13936 	 *
13937 	 * Here we take advantage of the value stack being just a duk_tval
13938 	 * array: we can just memcpy() the constants as long as we incref
13939 	 * them afterwards.
13940 	 */
13941 
13942 	h_data = (duk_hbuffer *) duk_known_hbuffer(thr, idx_base + 1);
13943 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC(h_data));
13944 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_fun, h_data);
13945 	DUK_HBUFFER_INCREF(thr, h_data);
13946 
13947 	tv1 = duk_get_tval(thr, idx_base + 2);  /* may be NULL if no constants or inner funcs */
13948 	DUK_ASSERT((count_const == 0 && count_funcs == 0) || tv1 != NULL);
13949 
13950 	q = fun_data;
13951 	duk_memcpy_unsafe((void *) q, (const void *) tv1, sizeof(duk_tval) * count_const);
13952 	for (n = count_const; n > 0; n--) {
13953 		DUK_TVAL_INCREF_FAST(thr, (duk_tval *) (void *) q);  /* no side effects */
13954 		q += sizeof(duk_tval);
13955 	}
13956 	tv1 += count_const;
13957 
13958 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_fun, (duk_hobject **) (void *) q);
13959 	for (n = count_funcs; n > 0; n--) {
13960 		duk_hobject *h_obj;
13961 
13962 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
13963 		h_obj = DUK_TVAL_GET_OBJECT(tv1);
13964 		DUK_ASSERT(h_obj != NULL);
13965 		tv1++;
13966 		DUK_HOBJECT_INCREF(thr, h_obj);
13967 
13968 		*((duk_hobject **) (void *) q) = h_obj;
13969 		q += sizeof(duk_hobject *);
13970 	}
13971 
13972 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_fun, (duk_instr_t *) (void *) q);
13973 
13974 	/* The function object is now reachable and refcounts are fine,
13975 	 * so we can pop off all the temporaries.
13976 	 */
13977 	DUK_DDD(DUK_DDDPRINT("function is reachable, reset top; func: %!iT", duk_get_tval(thr, idx_base)));
13978 	duk_set_top(thr, idx_base + 1);
13979 
13980 	/* Setup function properties. */
13981 	tmp32 = DUK_RAW_READ_U32_BE(p);
13982 	duk_push_u32(thr, tmp32);
13983 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
13984 
13985 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
13986 	p = duk__load_string_raw(thr, p);  /* -> [ func funcname ] */
13987 	func_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
13988 	DUK_ASSERT(func_env != NULL);
13989 	need_pop = 0;
13990 	if (DUK_HOBJECT_HAS_NAMEBINDING((duk_hobject *) h_fun)) {
13991 		/* Original function instance/template had NAMEBINDING.
13992 		 * Must create a lexical environment on loading to allow
13993 		 * recursive functions like 'function foo() { foo(); }'.
13994 		 */
13995 		duk_hdecenv *new_env;
13996 
13997 		new_env = duk_hdecenv_alloc(thr,
13998 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
13999 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
14000 		DUK_ASSERT(new_env != NULL);
14001 		DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
14002 		DUK_ASSERT(new_env->varmap == NULL);
14003 		DUK_ASSERT(new_env->regbase_byteoff == 0);
14004 		DUK_ASSERT_HDECENV_VALID(new_env);
14005 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
14006 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, func_env);
14007 		DUK_HOBJECT_INCREF(thr, func_env);
14008 
14009 		func_env = (duk_hobject *) new_env;
14010 
14011 		duk_push_hobject(thr, (duk_hobject *) new_env);
14012 
14013 		duk_dup_m2(thr);                                  /* -> [ func funcname env funcname ] */
14014 		duk_dup(thr, idx_base);                           /* -> [ func funcname env funcname func ] */
14015 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);  /* -> [ func funcname env ] */
14016 
14017 		need_pop = 1;  /* Need to pop env, but -after- updating h_fun and increfs. */
14018 	}
14019 	DUK_ASSERT(func_env != NULL);
14020 	DUK_HCOMPFUNC_SET_LEXENV(thr->heap, h_fun, func_env);
14021 	DUK_HCOMPFUNC_SET_VARENV(thr->heap, h_fun, func_env);
14022 	DUK_HOBJECT_INCREF(thr, func_env);
14023 	DUK_HOBJECT_INCREF(thr, func_env);
14024 	if (need_pop) {
14025 		duk_pop(thr);
14026 	}
14027 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
14028 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
14029 
14030 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
14031 	p = duk__load_string_raw(thr, p);
14032 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
14033 #endif  /* DUK_USE_FUNC_FILENAME_PROPERTY */
14034 
14035 	if (DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_fun)) {
14036 		/* Restore empty external .prototype only for constructable
14037 		 * functions.
14038 		 */
14039 		duk_push_object(thr);
14040 		duk_dup_m2(thr);
14041 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* func.prototype.constructor = func */
14042 		duk_compact_m1(thr);
14043 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);
14044 	}
14045 
14046 #if defined(DUK_USE_PC2LINE)
14047 	p = duk__load_buffer_raw(thr, p);
14048 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_WC);
14049 #endif  /* DUK_USE_PC2LINE */
14050 
14051 	duk_push_object(thr);  /* _Varmap */
14052 	for (;;) {
14053 		/* XXX: awkward */
14054 		p = duk__load_string_raw(thr, p);
14055 		if (duk_get_length(thr, -1) == 0) {
14056 			duk_pop(thr);
14057 			break;
14058 		}
14059 		tmp32 = DUK_RAW_READ_U32_BE(p);
14060 		duk_push_u32(thr, tmp32);
14061 		duk_put_prop(thr, -3);
14062 	}
14063 	duk_compact_m1(thr);
14064 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
14065 
14066 	/* _Formals may have been missing in the original function, which is
14067 	 * handled using a marker length.
14068 	 */
14069 	arr_limit = DUK_RAW_READ_U32_BE(p);
14070 	if (arr_limit != DUK__NO_FORMALS) {
14071 		duk_push_array(thr);  /* _Formals */
14072 		for (arr_idx = 0; arr_idx < arr_limit; arr_idx++) {
14073 			p = duk__load_string_raw(thr, p);
14074 			duk_put_prop_index(thr, -2, arr_idx);
14075 		}
14076 		duk_compact_m1(thr);
14077 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
14078 	} else {
14079 		DUK_DD(DUK_DDPRINT("no _Formals in dumped function"));
14080 	}
14081 
14082 	/* Return with final function pushed on stack top. */
14083 	DUK_DD(DUK_DDPRINT("final loaded function: %!iT", duk_get_tval(thr, -1)));
14084 	DUK_ASSERT_TOP(thr, idx_base + 1);
14085 	return p;
14086 
14087  format_error:
14088 	return NULL;
14089 }
14090 
duk_dump_function(duk_hthread * thr)14091 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14092 	duk_hcompfunc *func;
14093 	duk_bufwriter_ctx bw_ctx_alloc;
14094 	duk_bufwriter_ctx *bw_ctx = &bw_ctx_alloc;
14095 	duk_uint8_t *p;
14096 
14097 	DUK_ASSERT_API_ENTRY(thr);
14098 
14099 	/* Bound functions don't have all properties so we'd either need to
14100 	 * lookup the non-bound target function or reject bound functions.
14101 	 * For now, bound functions are rejected with TypeError.
14102 	 */
14103 	func = duk_require_hcompfunc(thr, -1);
14104 	DUK_ASSERT(func != NULL);
14105 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&func->obj));
14106 
14107 	/* Estimating the result size beforehand would be costly, so
14108 	 * start with a reasonable size and extend as needed.
14109 	 */
14110 	DUK_BW_INIT_PUSHBUF(thr, bw_ctx, DUK__BYTECODE_INITIAL_ALLOC);
14111 	p = DUK_BW_GET_PTR(thr, bw_ctx);
14112 	*p++ = DUK__SER_MARKER;
14113 	p = duk__dump_func(thr, func, bw_ctx, p);
14114 	DUK_BW_SET_PTR(thr, bw_ctx, p);
14115 	DUK_BW_COMPACT(thr, bw_ctx);
14116 
14117 	DUK_DD(DUK_DDPRINT("serialized result: %!T", duk_get_tval(thr, -1)));
14118 
14119 	duk_remove_m2(thr);  /* [ ... func buf ] -> [ ... buf ] */
14120 }
14121 
duk_load_function(duk_hthread * thr)14122 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14123 	duk_uint8_t *p_buf, *p, *p_end;
14124 	duk_size_t sz;
14125 
14126 	DUK_ASSERT_API_ENTRY(thr);
14127 
14128 	p_buf = (duk_uint8_t *) duk_require_buffer(thr, -1, &sz);
14129 	DUK_ASSERT(p_buf != NULL);
14130 
14131 	/* The caller is responsible for being sure that bytecode being loaded
14132 	 * is valid and trusted.  Invalid bytecode can cause memory unsafe
14133 	 * behavior directly during loading or later during bytecode execution
14134 	 * (instruction validation would be quite complex to implement).
14135 	 *
14136 	 * This signature check is the only sanity check for detecting
14137 	 * accidental invalid inputs.  The initial byte ensures no ordinary
14138 	 * string or Symbol will be accepted by accident.
14139 	 */
14140 	p = p_buf;
14141 	p_end = p_buf + sz;
14142 	if (sz < 1 || p[0] != DUK__SER_MARKER) {
14143 		goto format_error;
14144 	}
14145 	p++;
14146 
14147 	p = duk__load_func(thr, p, p_end);
14148 	if (p == NULL) {
14149 		goto format_error;
14150 	}
14151 
14152 	duk_remove_m2(thr);  /* [ ... buf func ] -> [ ... func ] */
14153 	return;
14154 
14155  format_error:
14156 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BYTECODE);
14157 	DUK_WO_NORETURN(return;);
14158 }
14159 
14160 #else  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14161 
duk_dump_function(duk_hthread * thr)14162 DUK_EXTERNAL void duk_dump_function(duk_hthread *thr) {
14163 	DUK_ASSERT_API_ENTRY(thr);
14164 	DUK_ERROR_UNSUPPORTED(thr);
14165 	DUK_WO_NORETURN(return;);
14166 }
14167 
duk_load_function(duk_hthread * thr)14168 DUK_EXTERNAL void duk_load_function(duk_hthread *thr) {
14169 	DUK_ASSERT_API_ENTRY(thr);
14170 	DUK_ERROR_UNSUPPORTED(thr);
14171 	DUK_WO_NORETURN(return;);
14172 }
14173 
14174 #endif  /* DUK_USE_BYTECODE_DUMP_SUPPORT */
14175 
14176 /* automatic undefs */
14177 #undef DUK__ASSERT_LEFT
14178 #undef DUK__BYTECODE_INITIAL_ALLOC
14179 #undef DUK__NO_FORMALS
14180 #undef DUK__SER_MARKER
14181 #undef DUK__SER_NUMBER
14182 #undef DUK__SER_STRING
14183 #line 1 "duk_api_call.c"
14184 /*
14185  *  Calls.
14186  *
14187  *  Protected variants should avoid ever throwing an error.  Must be careful
14188  *  to catch errors related to value stack manipulation and property lookup,
14189  *  not just the call itself.
14190  *
14191  *  The only exception is when arguments are insane, e.g. nargs/nrets are out
14192  *  of bounds; in such cases an error is thrown for two reasons.  First, we
14193  *  can't always respect the value stack input/output guarantees in such cases
14194  *  so the caller would end up with the value stack in an unexpected state.
14195  *  Second, an attempt to create an error might itself fail (although this
14196  *  could be avoided by pushing a preallocated object/string or a primitive
14197  *  value).
14198  */
14199 
14200 /* #include duk_internal.h -> already included */
14201 
14202 /*
14203  *  Helpers
14204  */
14205 
14206 struct duk__pcall_prop_args {
14207 	duk_idx_t obj_idx;
14208 	duk_idx_t nargs;
14209 	duk_small_uint_t call_flags;
14210 };
14211 typedef struct duk__pcall_prop_args duk__pcall_prop_args;
14212 
14213 struct duk__pcall_method_args {
14214 	duk_idx_t nargs;
14215 	duk_small_uint_t call_flags;
14216 };
14217 typedef struct duk__pcall_method_args duk__pcall_method_args;
14218 
14219 struct duk__pcall_args {
14220 	duk_idx_t nargs;
14221 	duk_small_uint_t call_flags;
14222 };
14223 typedef struct duk__pcall_args duk__pcall_args;
14224 
14225 /* Compute and validate idx_func for a certain 'nargs' and 'other'
14226  * parameter count (1 or 2, depending on whether 'this' binding is
14227  * present).
14228  */
duk__call_get_idx_func(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14229 DUK_LOCAL duk_idx_t duk__call_get_idx_func(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14230 	duk_idx_t idx_func;
14231 
14232 	/* XXX: byte arithmetic? */
14233 
14234 	DUK_ASSERT(other >= 0);
14235 
14236 	idx_func = duk_get_top(thr) - nargs - other;
14237 	if (DUK_UNLIKELY((idx_func | nargs) < 0)) {  /* idx_func < 0 || nargs < 0; OR sign bits */
14238 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14239 		DUK_WO_NORETURN(return 0;);
14240 	}
14241 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14242 	return idx_func;
14243 }
14244 
14245 /* Compute idx_func, assume index will be valid.  This is a valid assumption
14246  * for protected calls: nargs < 0 is checked explicitly and duk_safe_call()
14247  * validates the argument count.
14248  */
duk__call_get_idx_func_unvalidated(duk_hthread * thr,duk_idx_t nargs,duk_idx_t other)14249 DUK_LOCAL duk_idx_t duk__call_get_idx_func_unvalidated(duk_hthread *thr, duk_idx_t nargs, duk_idx_t other) {
14250 	duk_idx_t idx_func;
14251 
14252 	/* XXX: byte arithmetic? */
14253 
14254 	DUK_ASSERT(nargs >= 0);
14255 	DUK_ASSERT(other >= 0);
14256 
14257 	idx_func = duk_get_top(thr) - nargs - other;
14258 	DUK_ASSERT(idx_func >= 0);
14259 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14260 	return idx_func;
14261 }
14262 
14263 /* Prepare value stack for a method call through an object property.
14264  * May currently throw an error e.g. when getting the property.
14265  */
duk__call_prop_prep_stack(duk_hthread * thr,duk_idx_t normalized_obj_idx,duk_idx_t nargs)14266 DUK_LOCAL void duk__call_prop_prep_stack(duk_hthread *thr, duk_idx_t normalized_obj_idx, duk_idx_t nargs) {
14267 	DUK_ASSERT_CTX_VALID(thr);
14268 	DUK_ASSERT(nargs >= 0);
14269 
14270 	DUK_DDD(DUK_DDDPRINT("duk__call_prop_prep_stack, normalized_obj_idx=%ld, nargs=%ld, stacktop=%ld",
14271 	                     (long) normalized_obj_idx, (long) nargs, (long) duk_get_top(thr)));
14272 
14273 	/* [... key arg1 ... argN] */
14274 
14275 	/* duplicate key */
14276 	duk_dup(thr, -nargs - 1);  /* Note: -nargs alone would fail for nargs == 0, this is OK */
14277 	(void) duk_get_prop(thr, normalized_obj_idx);
14278 
14279 	DUK_DDD(DUK_DDDPRINT("func: %!T", (duk_tval *) duk_get_tval(thr, -1)));
14280 
14281 #if defined(DUK_USE_VERBOSE_ERRORS)
14282 	if (DUK_UNLIKELY(!duk_is_callable(thr, -1))) {
14283 		duk_tval *tv_targ;
14284 		duk_tval *tv_base;
14285 		duk_tval *tv_key;
14286 
14287 		tv_targ = DUK_GET_TVAL_NEGIDX(thr, -1);
14288 		tv_base = DUK_GET_TVAL_POSIDX(thr, normalized_obj_idx);
14289 		tv_key = DUK_GET_TVAL_NEGIDX(thr, -nargs - 2);
14290 		DUK_ASSERT(tv_targ >= thr->valstack_bottom && tv_targ < thr->valstack_top);
14291 		DUK_ASSERT(tv_base >= thr->valstack_bottom && tv_base < thr->valstack_top);
14292 		DUK_ASSERT(tv_key >= thr->valstack_bottom && tv_key < thr->valstack_top);
14293 
14294 		duk_call_setup_propcall_error(thr, tv_targ, tv_base, tv_key);
14295 	}
14296 #endif
14297 
14298 	/* [... key arg1 ... argN func] */
14299 
14300 	duk_replace(thr, -nargs - 2);
14301 
14302 	/* [... func arg1 ... argN] */
14303 
14304 	duk_dup(thr, normalized_obj_idx);
14305 	duk_insert(thr, -nargs - 1);
14306 
14307 	/* [... func this arg1 ... argN] */
14308 }
14309 
duk_call(duk_hthread * thr,duk_idx_t nargs)14310 DUK_EXTERNAL void duk_call(duk_hthread *thr, duk_idx_t nargs) {
14311 	duk_small_uint_t call_flags;
14312 	duk_idx_t idx_func;
14313 
14314 	DUK_ASSERT_API_ENTRY(thr);
14315 
14316 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14317 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14318 
14319 	duk_insert_undefined(thr, idx_func + 1);
14320 
14321 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14322 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14323 }
14324 
duk_call_method(duk_hthread * thr,duk_idx_t nargs)14325 DUK_EXTERNAL void duk_call_method(duk_hthread *thr, duk_idx_t nargs) {
14326 	duk_small_uint_t call_flags;
14327 	duk_idx_t idx_func;
14328 
14329 	DUK_ASSERT_API_ENTRY(thr);
14330 
14331 	idx_func = duk__call_get_idx_func(thr, nargs, 2);
14332 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14333 
14334 	call_flags = 0;  /* not protected, respect reclimit, not constructor */
14335 	duk_handle_call_unprotected(thr, idx_func, call_flags);
14336 }
14337 
duk_call_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14338 DUK_EXTERNAL void duk_call_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14339 	/*
14340 	 *  XXX: if duk_handle_call() took values through indices, this could be
14341 	 *  made much more sensible.  However, duk_handle_call() needs to fudge
14342 	 *  the 'this' and 'func' values to handle bound functions, which is now
14343 	 *  done "in-place", so this is not a trivial change.
14344 	 */
14345 
14346 	DUK_ASSERT_API_ENTRY(thr);
14347 
14348 	obj_idx = duk_require_normalize_index(thr, obj_idx);  /* make absolute */
14349 	if (DUK_UNLIKELY(nargs < 0)) {
14350 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14351 		DUK_WO_NORETURN(return;);
14352 	}
14353 
14354 	duk__call_prop_prep_stack(thr, obj_idx, nargs);
14355 
14356 	duk_call_method(thr, nargs);
14357 }
14358 
duk__pcall_raw(duk_hthread * thr,void * udata)14359 DUK_LOCAL duk_ret_t duk__pcall_raw(duk_hthread *thr, void *udata) {
14360 	duk__pcall_args *args;
14361 	duk_idx_t idx_func;
14362 	duk_int_t ret;
14363 
14364 	DUK_ASSERT_CTX_VALID(thr);
14365 	DUK_ASSERT(udata != NULL);
14366 
14367 	args = (duk__pcall_args *) udata;
14368 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 1);
14369 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14370 
14371 	duk_insert_undefined(thr, idx_func + 1);
14372 
14373 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14374 	DUK_ASSERT(ret == 0);
14375 	DUK_UNREF(ret);
14376 
14377 	return 1;
14378 }
14379 
duk_pcall(duk_hthread * thr,duk_idx_t nargs)14380 DUK_EXTERNAL duk_int_t duk_pcall(duk_hthread *thr, duk_idx_t nargs) {
14381 	duk__pcall_args args;
14382 
14383 	DUK_ASSERT_API_ENTRY(thr);
14384 
14385 	args.nargs = nargs;
14386 	if (DUK_UNLIKELY(nargs < 0)) {
14387 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14388 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14389 	}
14390 	args.call_flags = 0;
14391 
14392 	return duk_safe_call(thr, duk__pcall_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14393 }
14394 
duk__pcall_method_raw(duk_hthread * thr,void * udata)14395 DUK_LOCAL duk_ret_t duk__pcall_method_raw(duk_hthread *thr, void *udata) {
14396 	duk__pcall_method_args *args;
14397 	duk_idx_t idx_func;
14398 	duk_int_t ret;
14399 
14400 	DUK_ASSERT_CTX_VALID(thr);
14401 	DUK_ASSERT(udata != NULL);
14402 
14403 	args = (duk__pcall_method_args *) udata;
14404 
14405 	idx_func = duk__call_get_idx_func_unvalidated(thr, args->nargs, 2);
14406 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14407 
14408 	ret = duk_handle_call_unprotected(thr, idx_func, args->call_flags);
14409 	DUK_ASSERT(ret == 0);
14410 	DUK_UNREF(ret);
14411 
14412 	return 1;
14413 }
14414 
duk_pcall_method_flags(duk_hthread * thr,duk_idx_t nargs,duk_small_uint_t call_flags)14415 DUK_INTERNAL duk_int_t duk_pcall_method_flags(duk_hthread *thr, duk_idx_t nargs, duk_small_uint_t call_flags) {
14416 	duk__pcall_method_args args;
14417 
14418 	DUK_ASSERT_API_ENTRY(thr);
14419 
14420 	args.nargs = nargs;
14421 	if (DUK_UNLIKELY(nargs < 0)) {
14422 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14423 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14424 	}
14425 	args.call_flags = call_flags;
14426 
14427 	return duk_safe_call(thr, duk__pcall_method_raw, (void *) &args /*udata*/, nargs + 2 /*nargs*/, 1 /*nrets*/);
14428 }
14429 
duk_pcall_method(duk_hthread * thr,duk_idx_t nargs)14430 DUK_EXTERNAL duk_int_t duk_pcall_method(duk_hthread *thr, duk_idx_t nargs) {
14431 	DUK_ASSERT_API_ENTRY(thr);
14432 
14433 	return duk_pcall_method_flags(thr, nargs, 0);
14434 }
14435 
duk__pcall_prop_raw(duk_hthread * thr,void * udata)14436 DUK_LOCAL duk_ret_t duk__pcall_prop_raw(duk_hthread *thr, void *udata) {
14437 	duk__pcall_prop_args *args;
14438 	duk_idx_t obj_idx;
14439 	duk_int_t ret;
14440 
14441 	DUK_ASSERT_CTX_VALID(thr);
14442 	DUK_ASSERT(udata != NULL);
14443 
14444 	args = (duk__pcall_prop_args *) udata;
14445 
14446 	obj_idx = duk_require_normalize_index(thr, args->obj_idx);  /* make absolute */
14447 	duk__call_prop_prep_stack(thr, obj_idx, args->nargs);
14448 
14449 	ret = duk_handle_call_unprotected_nargs(thr, args->nargs, args->call_flags);
14450 	DUK_ASSERT(ret == 0);
14451 	DUK_UNREF(ret);
14452 	return 1;
14453 }
14454 
duk_pcall_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t nargs)14455 DUK_EXTERNAL duk_int_t duk_pcall_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t nargs) {
14456 	duk__pcall_prop_args args;
14457 
14458 	DUK_ASSERT_API_ENTRY(thr);
14459 
14460 	args.obj_idx = obj_idx;
14461 	args.nargs = nargs;
14462 	if (DUK_UNLIKELY(nargs < 0)) {
14463 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14464 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14465 	}
14466 	args.call_flags = 0;
14467 
14468 	return duk_safe_call(thr, duk__pcall_prop_raw, (void *) &args /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14469 }
14470 
duk_safe_call(duk_hthread * thr,duk_safe_call_function func,void * udata,duk_idx_t nargs,duk_idx_t nrets)14471 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) {
14472 	duk_int_t rc;
14473 
14474 	DUK_ASSERT_API_ENTRY(thr);
14475 
14476 	/* nargs condition; fail if: top - bottom < nargs
14477 	 *                      <=>  top < bottom + nargs
14478 	 * nrets condition; fail if: end - (top - nargs) < nrets
14479 	 *                      <=>  end - top + nargs < nrets
14480 	 *                      <=>  end + nargs < top + nrets
14481 	 */
14482 	/* XXX: check for any reserve? */
14483 
14484 	if (DUK_UNLIKELY((nargs | nrets) < 0 ||  /* nargs < 0 || nrets < 0; OR sign bits */
14485 	                 thr->valstack_top < thr->valstack_bottom + nargs ||        /* nargs too large compared to top */
14486 	                 thr->valstack_end + nargs < thr->valstack_top + nrets)) {  /* nrets too large compared to reserve */
14487 		DUK_D(DUK_DPRINT("not enough stack reserve for safe call or invalid arguments: "
14488 		                 "nargs=%ld < 0 (?), nrets=%ld < 0 (?), top=%ld < bottom=%ld + nargs=%ld (?), "
14489 		                 "end=%ld + nargs=%ld < top=%ld + nrets=%ld (?)",
14490 		                  (long) nargs,
14491 		                  (long) nrets,
14492 		                  (long) (thr->valstack_top - thr->valstack),
14493 		                  (long) (thr->valstack_bottom - thr->valstack),
14494 		                  (long) nargs,
14495 		                  (long) (thr->valstack_end - thr->valstack),
14496 		                  (long) nargs,
14497 		                  (long) (thr->valstack_top - thr->valstack),
14498 		                  (long) nrets));
14499 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14500 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14501 	}
14502 
14503 	rc = duk_handle_safe_call(thr,           /* thread */
14504 	                          func,          /* func */
14505 	                          udata,         /* udata */
14506 	                          nargs,         /* num_stack_args */
14507 	                          nrets);        /* num_stack_res */
14508 
14509 	return rc;
14510 }
14511 
duk_new(duk_hthread * thr,duk_idx_t nargs)14512 DUK_EXTERNAL void duk_new(duk_hthread *thr, duk_idx_t nargs) {
14513 	duk_idx_t idx_func;
14514 
14515 	DUK_ASSERT_API_ENTRY(thr);
14516 
14517 	idx_func = duk__call_get_idx_func(thr, nargs, 1);
14518 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
14519 
14520 	duk_push_object(thr);  /* default instance; internal proto updated by call handling */
14521 	duk_insert(thr, idx_func + 1);
14522 
14523 	duk_handle_call_unprotected(thr, idx_func, DUK_CALL_FLAG_CONSTRUCT);
14524 }
14525 
duk__pnew_helper(duk_hthread * thr,void * udata)14526 DUK_LOCAL duk_ret_t duk__pnew_helper(duk_hthread *thr, void *udata) {
14527 	duk_idx_t nargs;
14528 
14529 	DUK_ASSERT(udata != NULL);
14530 	nargs = *((duk_idx_t *) udata);
14531 
14532 	duk_new(thr, nargs);
14533 	return 1;
14534 }
14535 
duk_pnew(duk_hthread * thr,duk_idx_t nargs)14536 DUK_EXTERNAL duk_int_t duk_pnew(duk_hthread *thr, duk_idx_t nargs) {
14537 	duk_int_t rc;
14538 
14539 	DUK_ASSERT_API_ENTRY(thr);
14540 
14541 	/* For now, just use duk_safe_call() to wrap duk_new().  We can't
14542 	 * simply use a protected duk_handle_call() because pushing the
14543 	 * default instance might throw.
14544 	 */
14545 
14546 	if (DUK_UNLIKELY(nargs < 0)) {
14547 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
14548 		DUK_WO_NORETURN(return DUK_EXEC_ERROR;);
14549 	}
14550 
14551 	rc = duk_safe_call(thr, duk__pnew_helper, (void *) &nargs /*udata*/, nargs + 1 /*nargs*/, 1 /*nrets*/);
14552 	return rc;
14553 }
14554 
duk_is_constructor_call(duk_hthread * thr)14555 DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_hthread *thr) {
14556 	duk_activation *act;
14557 
14558 	DUK_ASSERT_API_ENTRY(thr);
14559 
14560 	act = thr->callstack_curr;
14561 	if (act != NULL) {
14562 		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
14563 	}
14564 	return 0;
14565 }
14566 
14567 /* XXX: Make this obsolete by adding a function flag for rejecting a
14568  * non-constructor call automatically?
14569  */
duk_require_constructor_call(duk_hthread * thr)14570 DUK_INTERNAL void duk_require_constructor_call(duk_hthread *thr) {
14571 	DUK_ASSERT_API_ENTRY(thr);
14572 
14573 	if (!duk_is_constructor_call(thr)) {
14574 		DUK_ERROR_TYPE(thr, DUK_STR_CONSTRUCT_ONLY);
14575 		DUK_WO_NORETURN(return;);
14576 	}
14577 }
14578 
duk_is_strict_call(duk_hthread * thr)14579 DUK_EXTERNAL duk_bool_t duk_is_strict_call(duk_hthread *thr) {
14580 	duk_activation *act;
14581 
14582 	/* For user code this could just return 1 (strict) always
14583 	 * because all Duktape/C functions are considered strict,
14584 	 * and strict is also the default when nothing is running.
14585 	 * However, Duktape may call this function internally when
14586 	 * the current activation is an ECMAScript function, so
14587 	 * this cannot be replaced by a 'return 1' without fixing
14588 	 * the internal call sites.
14589 	 */
14590 
14591 	DUK_ASSERT_API_ENTRY(thr);
14592 
14593 	act = thr->callstack_curr;
14594 	if (act != NULL) {
14595 		return ((act->flags & DUK_ACT_FLAG_STRICT) != 0 ? 1 : 0);
14596 	} else {
14597 		/* Strict by default. */
14598 		return 1;
14599 	}
14600 }
14601 
14602 /*
14603  *  Duktape/C function magic
14604  */
14605 
duk_get_current_magic(duk_hthread * thr)14606 DUK_EXTERNAL duk_int_t duk_get_current_magic(duk_hthread *thr) {
14607 	duk_activation *act;
14608 	duk_hobject *func;
14609 
14610 	DUK_ASSERT_API_ENTRY(thr);
14611 
14612 	act = thr->callstack_curr;
14613 	if (act) {
14614 		func = DUK_ACT_GET_FUNC(act);
14615 		if (!func) {
14616 			duk_tval *tv = &act->tv_func;
14617 			duk_small_uint_t lf_flags;
14618 			lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14619 			return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14620 		}
14621 		DUK_ASSERT(func != NULL);
14622 
14623 		if (DUK_HOBJECT_IS_NATFUNC(func)) {
14624 			duk_hnatfunc *nf = (duk_hnatfunc *) func;
14625 			return (duk_int_t) nf->magic;
14626 		}
14627 	}
14628 	return 0;
14629 }
14630 
duk_get_magic(duk_hthread * thr,duk_idx_t idx)14631 DUK_EXTERNAL duk_int_t duk_get_magic(duk_hthread *thr, duk_idx_t idx) {
14632 	duk_tval *tv;
14633 	duk_hobject *h;
14634 
14635 	DUK_ASSERT_API_ENTRY(thr);
14636 
14637 	tv = duk_require_tval(thr, idx);
14638 	if (DUK_TVAL_IS_OBJECT(tv)) {
14639 		h = DUK_TVAL_GET_OBJECT(tv);
14640 		DUK_ASSERT(h != NULL);
14641 		if (!DUK_HOBJECT_HAS_NATFUNC(h)) {
14642 			goto type_error;
14643 		}
14644 		return (duk_int_t) ((duk_hnatfunc *) h)->magic;
14645 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
14646 		duk_small_uint_t lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
14647 		return (duk_int_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
14648 	}
14649 
14650 	/* fall through */
14651  type_error:
14652 	DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
14653 	DUK_WO_NORETURN(return 0;);
14654 }
14655 
duk_set_magic(duk_hthread * thr,duk_idx_t idx,duk_int_t magic)14656 DUK_EXTERNAL void duk_set_magic(duk_hthread *thr, duk_idx_t idx, duk_int_t magic) {
14657 	duk_hnatfunc *nf;
14658 
14659 	DUK_ASSERT_API_ENTRY(thr);
14660 
14661 	nf = duk_require_hnatfunc(thr, idx);
14662 	DUK_ASSERT(nf != NULL);
14663 	nf->magic = (duk_int16_t) magic;
14664 }
14665 
14666 /*
14667  *  Misc helpers
14668  */
14669 
14670 /* Resolve a bound function on value stack top to a non-bound target
14671  * (leave other values as is).
14672  */
duk_resolve_nonbound_function(duk_hthread * thr)14673 DUK_INTERNAL void duk_resolve_nonbound_function(duk_hthread *thr) {
14674 	duk_tval *tv;
14675 
14676 	DUK_ASSERT_HTHREAD_VALID(thr);
14677 
14678 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
14679 	if (DUK_TVAL_IS_OBJECT(tv)) {
14680 		duk_hobject *h;
14681 
14682 		h = DUK_TVAL_GET_OBJECT(tv);
14683 		DUK_ASSERT(h != NULL);
14684 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
14685 			duk_push_tval(thr, &((duk_hboundfunc *) (void *) h)->target);
14686 			duk_replace(thr, -2);
14687 #if 0
14688 			DUK_TVAL_SET_TVAL(tv, &((duk_hboundfunc *) h)->target);
14689 			DUK_TVAL_INCREF(thr, tv);
14690 			DUK_HOBJECT_DECREF_NORZ(thr, h);
14691 #endif
14692 			/* Rely on Function.prototype.bind() on never creating a bound
14693 			 * function whose target is not proper.  This is now safe
14694 			 * because the target is not even an internal property but a
14695 			 * struct member.
14696 			 */
14697 			DUK_ASSERT(duk_is_lightfunc(thr, -1) || duk_is_callable(thr, -1));
14698 		}
14699 	}
14700 
14701 	/* Lightfuncs cannot be bound but are always callable and
14702 	 * constructable.
14703 	 */
14704 }
14705 #line 1 "duk_api_codec.c"
14706 /*
14707  *  Encoding and decoding basic formats: hex, base64.
14708  *
14709  *  These are in-place operations which may allow an optimized implementation.
14710  *
14711  *  Base-64: https://tools.ietf.org/html/rfc4648#section-4
14712  */
14713 
14714 /* #include duk_internal.h -> already included */
14715 
14716 /*
14717  *  Misc helpers
14718  */
14719 
14720 /* Shared handling for encode/decode argument.  Fast path handling for
14721  * buffer and string values because they're the most common.  In particular,
14722  * avoid creating a temporary string or buffer when possible.
14723  */
duk__prep_codec_arg(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)14724 DUK_LOCAL const duk_uint8_t *duk__prep_codec_arg(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
14725 	void *ptr;
14726 	duk_bool_t isbuffer;
14727 
14728 	DUK_ASSERT(duk_is_valid_index(thr, idx));  /* checked by caller */
14729 
14730 	/* XXX: with def_ptr set to a stack related pointer, isbuffer could
14731 	 * be removed from the helper?
14732 	 */
14733 	ptr = duk_get_buffer_data_raw(thr, idx, out_len, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, &isbuffer);
14734 	if (isbuffer) {
14735 		DUK_ASSERT(*out_len == 0 || ptr != NULL);
14736 		return (const duk_uint8_t *) ptr;
14737 	}
14738 	return (const duk_uint8_t *) duk_to_lstring(thr, idx, out_len);
14739 }
14740 
14741 /*
14742  *  Base64
14743  */
14744 
14745 #if defined(DUK_USE_BASE64_SUPPORT)
14746 /* Bytes emitted for number of padding characters in range [0,4]. */
14747 DUK_LOCAL const duk_int8_t duk__base64_decode_nequal_step[5] = {
14748 	3,   /* #### -> 24 bits, emit 3 bytes */
14749 	2,   /* ###= -> 18 bits, emit 2 bytes */
14750 	1,   /* ##== -> 12 bits, emit 1 byte */
14751 	-1,  /* #=== -> 6 bits, error */
14752 	0,   /* ==== -> 0 bits, emit 0 bytes */
14753 };
14754 
14755 #if defined(DUK_USE_BASE64_FASTPATH)
14756 DUK_LOCAL const duk_uint8_t duk__base64_enctab_fast[64] = {
14757 	0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU, 0x50U,  /* A...P */
14758 	0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U, 0x5aU, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U,  /* Q...f */
14759 	0x67U, 0x68U, 0x69U, 0x6aU, 0x6bU, 0x6cU, 0x6dU, 0x6eU, 0x6fU, 0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U,  /* g...v */
14760 	0x77U, 0x78U, 0x79U, 0x7aU, 0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U, 0x2bU, 0x2fU   /* w.../ */
14761 };
14762 #endif  /* DUK_USE_BASE64_FASTPATH */
14763 
14764 #if defined(DUK_USE_BASE64_FASTPATH)
14765 /* Decode table for one byte of input:
14766  *   -1 = allowed whitespace
14767  *   -2 = padding
14768  *   -3 = error
14769  *    0...63 decoded bytes
14770  */
14771 DUK_LOCAL const duk_int8_t duk__base64_dectab_fast[256] = {
14772 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -1, -1, -3, -3, -1, -3, -3,  /* 0x00...0x0f */
14773 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x10...0x1f */
14774 	-1, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, 62, -3, -3, -3, 63,  /* 0x20...0x2f */
14775 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -3, -3, -3, -2, -3, -3,  /* 0x30...0x3f */
14776 	-3,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  /* 0x40...0x4f */
14777 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -3, -3, -3, -3, -3,  /* 0x50...0x5f */
14778 	-3, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  /* 0x60...0x6f */
14779 	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -3, -3, -3, -3, -3,  /* 0x70...0x7f */
14780 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x80...0x8f */
14781 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0x90...0x9f */
14782 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xa0...0xaf */
14783 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xb0...0xbf */
14784 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xc0...0xcf */
14785 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xd0...0xdf */
14786 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,  /* 0xe0...0xef */
14787 	-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3   /* 0xf0...0xff */
14788 };
14789 #endif  /* DUK_USE_BASE64_FASTPATH */
14790 
14791 #if defined(DUK_USE_BASE64_FASTPATH)
duk__base64_encode_fast_3(const duk_uint8_t * src,duk_uint8_t * dst)14792 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_3(const duk_uint8_t *src, duk_uint8_t *dst) {
14793 	duk_uint_t t;
14794 
14795 	t = (duk_uint_t) src[0];
14796 	t = (t << 8) + (duk_uint_t) src[1];
14797 	t = (t << 8) + (duk_uint_t) src[2];
14798 
14799 	dst[0] = duk__base64_enctab_fast[t >> 18];
14800 	dst[1] = duk__base64_enctab_fast[(t >> 12) & 0x3fU];
14801 	dst[2] = duk__base64_enctab_fast[(t >> 6) & 0x3fU];
14802 	dst[3] = duk__base64_enctab_fast[t & 0x3fU];
14803 
14804 #if 0
14805 	/* Tested: not faster on x64, most likely due to aliasing between
14806 	 * output and input index computation.
14807 	 */
14808 	/* aaaaaabb bbbbcccc ccdddddd */
14809 	dst[0] = duk__base64_enctab_fast[(src[0] >> 2) & 0x3fU];
14810 	dst[1] = duk__base64_enctab_fast[((src[0] << 4) & 0x30U) | ((src[1] >> 4) & 0x0fU)];
14811 	dst[2] = duk__base64_enctab_fast[((src[1] << 2) & 0x3fU) | ((src[2] >> 6) & 0x03U)];
14812 	dst[3] = duk__base64_enctab_fast[src[2] & 0x3fU];
14813 #endif
14814 }
14815 
duk__base64_encode_fast_2(const duk_uint8_t * src,duk_uint8_t * dst)14816 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_2(const duk_uint8_t *src, duk_uint8_t *dst) {
14817 	duk_uint_t t;
14818 
14819 	t = (duk_uint_t) src[0];
14820 	t = (t << 8) + (duk_uint_t) src[1];
14821 	dst[0] = duk__base64_enctab_fast[t >> 10];           /* XXXXXX-- -------- */
14822 	dst[1] = duk__base64_enctab_fast[(t >> 4) & 0x3fU];  /* ------XX XXXX---- */
14823 	dst[2] = duk__base64_enctab_fast[(t << 2) & 0x3fU];  /* -------- ----XXXX */
14824 	dst[3] = DUK_ASC_EQUALS;
14825 }
14826 
duk__base64_encode_fast_1(const duk_uint8_t * src,duk_uint8_t * dst)14827 DUK_LOCAL DUK_ALWAYS_INLINE void duk__base64_encode_fast_1(const duk_uint8_t *src, duk_uint8_t *dst) {
14828 	duk_uint_t t;
14829 
14830 	t = (duk_uint_t) src[0];
14831 	dst[0] = duk__base64_enctab_fast[t >> 2];            /* XXXXXX-- */
14832 	dst[1] = duk__base64_enctab_fast[(t << 4) & 0x3fU];  /* ------XX */
14833 	dst[2] = DUK_ASC_EQUALS;
14834 	dst[3] = DUK_ASC_EQUALS;
14835 }
14836 
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14837 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14838 	duk_size_t n;
14839 	const duk_uint8_t *p;
14840 	duk_uint8_t *q;
14841 
14842 	n = srclen;
14843 	p = src;
14844 	q = dst;
14845 
14846 	if (n >= 16U) {
14847 		/* Fast path, unrolled by 4, allows interleaving.  Process
14848 		 * 12-byte input chunks which encode to 16-char output chunks.
14849 		 * Only enter when at least one block is emitted (avoids div+mul
14850 		 * for short inputs too).
14851 		 */
14852 		const duk_uint8_t *p_end_fast;
14853 
14854 		p_end_fast = p + ((n / 12U) * 12U);
14855 		DUK_ASSERT(p_end_fast >= p + 12);
14856 		do {
14857 			duk__base64_encode_fast_3(p, q);
14858 			duk__base64_encode_fast_3(p + 3, q + 4);
14859 			duk__base64_encode_fast_3(p + 6, q + 8);
14860 			duk__base64_encode_fast_3(p + 9, q + 12);
14861 			p += 12;
14862 			q += 16;
14863 		} while (DUK_LIKELY(p != p_end_fast));
14864 
14865 		DUK_ASSERT(src + srclen >= p);
14866 		n = (duk_size_t) (src + srclen - p);
14867 		DUK_ASSERT(n < 12U);
14868 	}
14869 
14870 	/* Remainder. */
14871 	while (n >= 3U) {
14872 		duk__base64_encode_fast_3(p, q);
14873 		p += 3;
14874 		q += 4;
14875 		n -= 3U;
14876 	}
14877 	DUK_ASSERT(n == 0U || n == 1U || n == 2U);
14878 	if (n == 1U) {
14879 		duk__base64_encode_fast_1(p, q);
14880 #if 0  /* Unnecessary. */
14881 		p += 1;
14882 		q += 4;
14883 		n -= 1U;
14884 #endif
14885 	} else if (n == 2U) {
14886 		duk__base64_encode_fast_2(p, q);
14887 #if 0  /* Unnecessary. */
14888 		p += 2;
14889 		q += 4;
14890 		n -= 2U;
14891 #endif
14892 	} else {
14893 		DUK_ASSERT(n == 0U);  /* nothing to do */
14894 		;
14895 	}
14896 }
14897 #else  /* DUK_USE_BASE64_FASTPATH */
duk__base64_encode_helper(const duk_uint8_t * src,duk_size_t srclen,duk_uint8_t * dst)14898 DUK_LOCAL void duk__base64_encode_helper(const duk_uint8_t *src, duk_size_t srclen, duk_uint8_t *dst) {
14899 	duk_small_uint_t i, npad;
14900 	duk_uint_t t, x, y;
14901 	const duk_uint8_t *p;
14902 	const duk_uint8_t *p_end;
14903 	duk_uint8_t *q;
14904 
14905 	p = src;
14906 	p_end = src + srclen;
14907 	q = dst;
14908 	npad = 0U;
14909 
14910 	while (p < p_end) {
14911 		/* Read 3 bytes into 't', padded by zero. */
14912 		t = 0;
14913 		for (i = 0; i < 3; i++) {
14914 			t = t << 8;
14915 			if (p < p_end) {
14916 				t += (duk_uint_t) (*p++);
14917 			} else {
14918 				/* This only happens on the last loop and we're
14919 				 * guaranteed to exit on the next loop.
14920 				 */
14921 				npad++;
14922 			}
14923 		}
14924 		DUK_ASSERT(npad <= 2U);
14925 
14926 		/* Emit 4 encoded characters.  If npad > 0, some of the
14927 		 * chars will be incorrect (zero bits) but we fix up the
14928 		 * padding after the loop.  A straightforward 64-byte
14929 		 * lookup would be faster and cleaner, but this is shorter.
14930 		 */
14931 		for (i = 0; i < 4; i++) {
14932 			x = ((t >> 18) & 0x3fU);
14933 			t = t << 6;
14934 
14935 			if (x <= 51U) {
14936 				if (x <= 25) {
14937 					y = x + DUK_ASC_UC_A;
14938 				} else {
14939 					y = x - 26 + DUK_ASC_LC_A;
14940 				}
14941 			} else {
14942 				if (x <= 61U) {
14943 					y = x - 52 + DUK_ASC_0;
14944 				} else if (x == 62) {
14945 					y = DUK_ASC_PLUS;
14946 				} else {
14947 					DUK_ASSERT(x == 63);
14948 					y = DUK_ASC_SLASH;
14949 				}
14950 			}
14951 
14952 			*q++ = (duk_uint8_t) y;
14953 		}
14954 	}
14955 
14956 	/* Handle padding by rewriting 0-2 bogus characters at the end.
14957 	 *
14958 	 *  Missing bytes    npad     base64 example
14959 	 *    0               0         ####
14960 	 *    1               1         ###=
14961 	 *    2               2         ##==
14962 	 */
14963 	DUK_ASSERT(npad <= 2U);
14964 	while (npad > 0U) {
14965 		*(q - npad) = DUK_ASC_EQUALS;
14966 		npad--;
14967 	}
14968 }
14969 #endif  /* DUK_USE_BASE64_FASTPATH */
14970 
14971 #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)14972 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) {
14973 	duk_int_t x;
14974 	duk_uint_t t;
14975 	duk_small_uint_t n_equal;
14976 	duk_int8_t step;
14977 	const duk_uint8_t *p;
14978 	const duk_uint8_t *p_end;
14979 	const duk_uint8_t *p_end_safe;
14980 	duk_uint8_t *q;
14981 
14982 	p = src;
14983 	p_end = src + srclen;
14984 	p_end_safe = p_end - 8;  /* If 'src <= src_end_safe', safe to read 8 bytes. */
14985 	q = dst;
14986 
14987 	/* Alternate between a fast path which processes clean groups with no
14988 	 * padding or whitespace, and a slow path which processes one arbitrary
14989 	 * group and then re-enters the fast path.  This handles e.g. base64
14990 	 * with newlines reasonably well because the majority of a line is in
14991 	 * the fast path.
14992 	 */
14993 	for (;;) {
14994 		/* Fast path, on each loop handle two 4-char input groups.
14995 		 * If both are clean, emit 6 bytes and continue.  If first
14996 		 * is clean, emit 3 bytes and drop out; otherwise emit
14997 		 * nothing and drop out.  This approach could be extended to
14998 		 * more groups per loop, but for inputs with e.g. periodic
14999 		 * newlines (which are common) it might not be an improvement.
15000 		 */
15001 		while (DUK_LIKELY(p <= p_end_safe)) {
15002 			duk_int_t t1, t2;
15003 
15004 			/* The lookup byte is intentionally sign extended to
15005 			 * (at least) 32 bits and then ORed.  This ensures
15006 			 * that is at least 1 byte is negative, the highest
15007 			 * bit of the accumulator will be set at the end and
15008 			 * we don't need to check every byte.
15009 			 *
15010 			 * Read all input bytes first before writing output
15011 			 * bytes to minimize aliasing.
15012 			 */
15013 			DUK_DDD(DUK_DDDPRINT("fast loop: p=%p, p_end_safe=%p, p_end=%p",
15014 			                     (const void *) p, (const void *) p_end_safe, (const void *) p_end));
15015 
15016 			t1 = (duk_int_t) duk__base64_dectab_fast[p[0]];
15017 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[1]];
15018 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[2]];
15019 			t1 = (duk_int_t) ((duk_uint_t) t1 << 6) | (duk_int_t) duk__base64_dectab_fast[p[3]];
15020 
15021 			t2 = (duk_int_t) duk__base64_dectab_fast[p[4]];
15022 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[5]];
15023 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[6]];
15024 			t2 = (duk_int_t) ((duk_uint_t) t2 << 6) | (duk_int_t) duk__base64_dectab_fast[p[7]];
15025 
15026 			q[0] = (duk_uint8_t) (((duk_uint_t) t1 >> 16) & 0xffU);
15027 			q[1] = (duk_uint8_t) (((duk_uint_t) t1 >> 8) & 0xffU);
15028 			q[2] = (duk_uint8_t) ((duk_uint_t) t1 & 0xffU);
15029 
15030 			q[3] = (duk_uint8_t) (((duk_uint_t) t2 >> 16) & 0xffU);
15031 			q[4] = (duk_uint8_t) (((duk_uint_t) t2 >> 8) & 0xffU);
15032 			q[5] = (duk_uint8_t) ((duk_uint_t) t2 & 0xffU);
15033 
15034 			/* Optimistic check using one branch. */
15035 			if (DUK_LIKELY((t1 | t2) >= 0)) {
15036 				p += 8;
15037 				q += 6;
15038 			} else if (t1 >= 0) {
15039 				DUK_DDD(DUK_DDDPRINT("fast loop first group was clean, second was not, process one slow path group"));
15040 				DUK_ASSERT(t2 < 0);
15041 				p += 4;
15042 				q += 3;
15043 				break;
15044 			} else {
15045 				DUK_DDD(DUK_DDDPRINT("fast loop first group was not clean, second does not matter, process one slow path group"));
15046 				DUK_ASSERT(t1 < 0);
15047 				break;
15048 			}
15049 		}  /* fast path */
15050 
15051 		/* Slow path step 1: try to scan a 4-character encoded group,
15052 		 * end-of-input, or start-of-padding.  We exit with:
15053 		 *   1. n_chars == 4: full group, no padding, no end-of-input.
15054 		 *   2. n_chars < 4: partial group (may also be 0), encountered
15055 		 *      padding or end of input.
15056 		 *
15057 		 * The accumulator is initialized to 1; this allows us to detect
15058 		 * a full group by comparing >= 0x1000000 without an extra
15059 		 * counter variable.
15060 		 */
15061 		t = 1UL;
15062 		for (;;) {
15063 			DUK_DDD(DUK_DDDPRINT("slow loop: p=%p, p_end=%p, t=%lu",
15064 			                     (const void *) p, (const void *) p_end, (unsigned long) t));
15065 
15066 			if (DUK_LIKELY(p < p_end)) {
15067 				x = duk__base64_dectab_fast[*p++];
15068 				if (DUK_LIKELY(x >= 0)) {
15069 					DUK_ASSERT(x >= 0 && x <= 63);
15070 					t = (t << 6) + (duk_uint_t) x;
15071 					if (t >= 0x1000000UL) {
15072 						break;
15073 					}
15074 				} else if (x == -1) {
15075 					continue;  /* allowed ascii whitespace */
15076 				} else if (x == -2) {
15077 					p--;
15078 					break;  /* start of padding */
15079 				} else {
15080 					DUK_ASSERT(x == -3);
15081 					goto decode_error;
15082 				}
15083 			} else {
15084 				break;  /* end of input */
15085 			}
15086 		}  /* slow path step 1 */
15087 
15088 		/* Complete the padding by simulating pad characters,
15089 		 * regardless of actual input padding chars.
15090 		 */
15091 		n_equal = 0;
15092 		while (t < 0x1000000UL) {
15093 			t = (t << 6) + 0U;
15094 			n_equal++;
15095 		}
15096 
15097 		/* Slow path step 2: deal with full/partial group, padding,
15098 		 * etc.  Note that for num chars in [0,3] we intentionally emit
15099 		 * 3 bytes but don't step forward that much, buffer space is
15100 		 * guaranteed in setup.
15101 		 *
15102 		 *  num chars:
15103 		 *   0      ####   no output (= step 0)
15104 		 *   1      #===   reject, 6 bits of data
15105 		 *   2      ##==   12 bits of data, output 1 byte (= step 1)
15106 		 *   3      ###=   18 bits of data, output 2 bytes (= step 2)
15107 		 *   4      ####   24 bits of data, output 3 bytes (= step 3)
15108 		 */
15109 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15110 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15111 		q[2] = (duk_uint8_t) (t & 0xffU);
15112 
15113 		DUK_ASSERT(n_equal <= 4);
15114 		step = duk__base64_decode_nequal_step[n_equal];
15115 		if (DUK_UNLIKELY(step < 0)) {
15116 			goto decode_error;
15117 		}
15118 		q += step;
15119 
15120 		/* Slow path step 3: read and ignore padding and whitespace
15121 		 * until (a) next non-padding and non-whitespace character
15122 		 * after which we resume the fast path, or (b) end of input.
15123 		 * This allows us to accept missing, partial, full, and extra
15124 		 * padding cases uniformly.  We also support concatenated
15125 		 * base-64 documents because we resume scanning afterwards.
15126 		 *
15127 		 * Note that to support concatenated documents well, the '='
15128 		 * padding found inside the input must also allow for 'extra'
15129 		 * padding.  For example, 'Zm===' decodes to 'f' and has one
15130 		 * extra padding char.  So, 'Zm===Zm' should decode 'ff', even
15131 		 * though the standard break-up would be 'Zm==' + '=Zm' which
15132 		 * doesn't make sense.
15133 		 *
15134 		 * We also accept prepended padding like '==Zm9', because it
15135 		 * is equivalent to an empty document with extra padding ('==')
15136 		 * followed by a valid document.
15137 		 */
15138 
15139 		for (;;) {
15140 			if (DUK_UNLIKELY(p >= p_end)) {
15141 				goto done;
15142 			}
15143 			x = duk__base64_dectab_fast[*p++];
15144 			if (x == -1 || x == -2) {
15145 				;  /* padding or whitespace, keep eating */
15146 			} else {
15147 				p--;
15148 				break;  /* backtrack and go back to fast path, even for -1 */
15149 			}
15150 		}  /* slow path step 3 */
15151 	}  /* outer fast+slow path loop */
15152 
15153  done:
15154 	DUK_DDD(DUK_DDDPRINT("done; p=%p, p_end=%p",
15155 	                     (const void *) p, (const void *) p_end));
15156 
15157 	DUK_ASSERT(p == p_end);
15158 
15159 	*out_dst_final = q;
15160 	return 1;
15161 
15162  decode_error:
15163 	return 0;
15164 }
15165 #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)15166 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) {
15167 	duk_uint_t t, x;
15168 	duk_int_t y;
15169 	duk_int8_t step;
15170 	const duk_uint8_t *p;
15171 	const duk_uint8_t *p_end;
15172 	duk_uint8_t *q;
15173 	/* 0x09, 0x0a, or 0x0d */
15174 	duk_uint32_t mask_white = (1U << 9) | (1U << 10) | (1U << 13);
15175 
15176 	/* 't' tracks progress of the decoded group:
15177 	 *
15178 	 *  t == 1             no valid chars yet
15179 	 *  t >= 0x40          1x6 = 6 bits shifted in
15180 	 *  t >= 0x1000        2x6 = 12 bits shifted in
15181 	 *  t >= 0x40000       3x6 = 18 bits shifted in
15182 	 *  t >= 0x1000000     4x6 = 24 bits shifted in
15183 	 *
15184 	 * By initializing t=1 there's no need for a separate counter for
15185 	 * the number of characters found so far.
15186 	 */
15187 	p = src;
15188 	p_end = src + srclen;
15189 	q = dst;
15190 	t = 1UL;
15191 
15192 	for (;;) {
15193 		duk_small_uint_t n_equal;
15194 
15195 		DUK_ASSERT(t >= 1U);
15196 		if (p >= p_end) {
15197 			/* End of input: if input exists, treat like
15198 			 * start of padding, finish the block, then
15199 			 * re-enter here to see we're done.
15200 			 */
15201 			if (t == 1U) {
15202 				break;
15203 			} else {
15204 				goto simulate_padding;
15205 			}
15206 		}
15207 
15208 		x = *p++;
15209 
15210 		if (x >= 0x41U) {
15211 			/* Valid: a-z and A-Z. */
15212 			DUK_ASSERT(x >= 0x41U && x <= 0xffU);
15213 			if (x >= 0x61U && x <= 0x7aU) {
15214 				y = (duk_int_t) x - 0x61 + 26;
15215 			} else if (x <= 0x5aU) {
15216 				y = (duk_int_t) x - 0x41;
15217 			} else {
15218 				goto decode_error;
15219 			}
15220 		} else if (x >= 0x30U) {
15221 			/* Valid: 0-9 and =. */
15222 			DUK_ASSERT(x >= 0x30U && x <= 0x40U);
15223 			if (x <= 0x39U) {
15224 				y = (duk_int_t) x - 0x30 + 52;
15225 			} else if (x == 0x3dU) {
15226 				/* Skip padding and whitespace unless we're in the
15227 				 * middle of a block.  Otherwise complete group by
15228 				 * simulating shifting in the correct padding.
15229 				 */
15230 				if (t == 1U) {
15231 					continue;
15232 				}
15233 				goto simulate_padding;
15234 			} else {
15235 				goto decode_error;
15236 			}
15237 		} else if (x >= 0x20U) {
15238 			/* Valid: +, /, and 0x20 whitespace. */
15239 			DUK_ASSERT(x >= 0x20U && x <= 0x2fU);
15240 			if (x == 0x2bU) {
15241 				y = 62;
15242 			} else if (x == 0x2fU) {
15243 				y = 63;
15244 			} else if (x == 0x20U) {
15245 				continue;
15246 			} else {
15247 				goto decode_error;
15248 			}
15249 		} else {
15250 			/* Valid: whitespace. */
15251 			duk_uint32_t m;
15252 			DUK_ASSERT(x < 0x20U);  /* 0x00 to 0x1f */
15253 			m = (1U << x);
15254 			if (mask_white & m) {
15255 				/* Allow basic ASCII whitespace. */
15256 				continue;
15257 			} else {
15258 				goto decode_error;
15259 			}
15260 		}
15261 
15262 		DUK_ASSERT(y >= 0 && y <= 63);
15263 		t = (t << 6) + (duk_uint_t) y;
15264 		if (t < 0x1000000UL) {
15265 			continue;
15266 		}
15267 		/* fall through; no padding will be added */
15268 
15269 	 simulate_padding:
15270 		n_equal = 0;
15271 		while (t < 0x1000000UL) {
15272 			t = (t << 6) + 0U;
15273 			n_equal++;
15274 		}
15275 
15276 		/* Output 3 bytes from 't' and advance as needed. */
15277 		q[0] = (duk_uint8_t) ((t >> 16) & 0xffU);
15278 		q[1] = (duk_uint8_t) ((t >> 8) & 0xffU);
15279 		q[2] = (duk_uint8_t) (t & 0xffU);
15280 
15281 		DUK_ASSERT(n_equal <= 4U);
15282 		step = duk__base64_decode_nequal_step[n_equal];
15283 		if (step < 0) {
15284 			goto decode_error;
15285 		}
15286 		q += step;
15287 
15288 		/* Re-enter loop.  The actual padding characters are skipped
15289 		 * by the main loop.  This handles cases like missing, partial,
15290 		 * full, and extra padding, and allows parsing of concatenated
15291 		 * documents (with extra padding) like: Zm===Zm.  Also extra
15292 		 * prepended padding is accepted: ===Zm9v.
15293 		 */
15294 		t = 1U;
15295 	}
15296 	DUK_ASSERT(t == 1UL);
15297 
15298 	*out_dst_final = q;
15299 	return 1;
15300 
15301  decode_error:
15302 	return 0;
15303 }
15304 #endif  /* DUK_USE_BASE64_FASTPATH */
15305 
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15306 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15307 	const duk_uint8_t *src;
15308 	duk_size_t srclen;
15309 	duk_size_t dstlen;
15310 	duk_uint8_t *dst;
15311 	const char *ret;
15312 
15313 	DUK_ASSERT_API_ENTRY(thr);
15314 
15315 	idx = duk_require_normalize_index(thr, idx);
15316 	src = duk__prep_codec_arg(thr, idx, &srclen);
15317 	/* Note: for srclen=0, src may be NULL */
15318 
15319 	/* Compute exact output length.  Computation must not wrap; this
15320 	 * limit works for 32-bit size_t:
15321 	 * >>> srclen = 3221225469
15322 	 * >>> '%x' % ((srclen + 2) / 3 * 4)
15323 	 * 'fffffffc'
15324 	 */
15325 	if (srclen > 3221225469UL) {
15326 		goto type_error;
15327 	}
15328 	dstlen = (srclen + 2U) / 3U * 4U;
15329 	dst = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, dstlen);
15330 
15331 	duk__base64_encode_helper((const duk_uint8_t *) src, srclen, dst);
15332 
15333 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15334 	duk_replace(thr, idx);
15335 	return ret;
15336 
15337  type_error:
15338 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_ENCODE_FAILED);
15339 	DUK_WO_NORETURN(return NULL;);
15340 }
15341 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15342 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15343 	const duk_uint8_t *src;
15344 	duk_size_t srclen;
15345 	duk_size_t dstlen;
15346 	duk_uint8_t *dst;
15347 	duk_uint8_t *dst_final;
15348 
15349 	DUK_ASSERT_API_ENTRY(thr);
15350 
15351 	idx = duk_require_normalize_index(thr, idx);
15352 	src = duk__prep_codec_arg(thr, idx, &srclen);
15353 
15354 	/* Round up and add safety margin.  Avoid addition before division to
15355 	 * avoid possibility of wrapping.  Margin includes +3 for rounding up,
15356 	 * and +3 for one extra group: the decoder may emit and then backtrack
15357 	 * a full group (3 bytes) from zero-sized input for technical reasons.
15358 	 * Similarly, 'xx' may ecause 1+3 = bytes to be emitted and then
15359 	 * backtracked.
15360 	 */
15361 	dstlen = (srclen / 4) * 3 + 6;  /* upper limit, assuming no whitespace etc */
15362 	dst = (duk_uint8_t *) duk_push_dynamic_buffer(thr, dstlen);
15363 	/* Note: for dstlen=0, dst may be NULL */
15364 
15365 	if (!duk__base64_decode_helper((const duk_uint8_t *) src, srclen, dst, &dst_final)) {
15366 		goto type_error;
15367 	}
15368 
15369 	/* XXX: convert to fixed buffer? */
15370 	(void) duk_resize_buffer(thr, -1, (duk_size_t) (dst_final - dst));
15371 	duk_replace(thr, idx);
15372 	return;
15373 
15374  type_error:
15375 	DUK_ERROR_TYPE(thr, DUK_STR_BASE64_DECODE_FAILED);
15376 	DUK_WO_NORETURN(return;);
15377 }
15378 #else  /* DUK_USE_BASE64_SUPPORT */
duk_base64_encode(duk_hthread * thr,duk_idx_t idx)15379 DUK_EXTERNAL const char *duk_base64_encode(duk_hthread *thr, duk_idx_t idx) {
15380 	DUK_UNREF(idx);
15381 	DUK_ERROR_UNSUPPORTED(thr);
15382 	DUK_WO_NORETURN(return;);
15383 }
15384 
duk_base64_decode(duk_hthread * thr,duk_idx_t idx)15385 DUK_EXTERNAL void duk_base64_decode(duk_hthread *thr, duk_idx_t idx) {
15386 	DUK_UNREF(idx);
15387 	DUK_ERROR_UNSUPPORTED(thr);
15388 	DUK_WO_NORETURN(return;);
15389 }
15390 #endif  /* DUK_USE_BASE64_SUPPORT */
15391 
15392 /*
15393  *  Hex
15394  */
15395 
15396 #if defined(DUK_USE_HEX_SUPPORT)
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15397 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15398 	const duk_uint8_t *inp;
15399 	duk_size_t len;
15400 	duk_size_t i;
15401 	duk_uint8_t *buf;
15402 	const char *ret;
15403 #if defined(DUK_USE_HEX_FASTPATH)
15404 	duk_size_t len_safe;
15405 	duk_uint16_t *p16;
15406 #endif
15407 
15408 	DUK_ASSERT_API_ENTRY(thr);
15409 
15410 	idx = duk_require_normalize_index(thr, idx);
15411 	inp = duk__prep_codec_arg(thr, idx, &len);
15412 	DUK_ASSERT(inp != NULL || len == 0);
15413 
15414 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15415 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len * 2);
15416 	DUK_ASSERT(buf != NULL);
15417 
15418 #if defined(DUK_USE_HEX_FASTPATH)
15419 	DUK_ASSERT((((duk_size_t) buf) & 0x01U) == 0);   /* pointer is aligned, guaranteed for fixed buffer */
15420 	p16 = (duk_uint16_t *) (void *) buf;
15421 	len_safe = len & ~0x03U;
15422 	for (i = 0; i < len_safe; i += 4) {
15423 		p16[0] = duk_hex_enctab[inp[i]];
15424 		p16[1] = duk_hex_enctab[inp[i + 1]];
15425 		p16[2] = duk_hex_enctab[inp[i + 2]];
15426 		p16[3] = duk_hex_enctab[inp[i + 3]];
15427 		p16 += 4;
15428 	}
15429 	for (; i < len; i++) {
15430 		*p16++ = duk_hex_enctab[inp[i]];
15431 	}
15432 #else  /* DUK_USE_HEX_FASTPATH */
15433 	for (i = 0; i < len; i++) {
15434 		duk_small_uint_t t;
15435 		t = (duk_small_uint_t) inp[i];
15436 		buf[i*2 + 0] = duk_lc_digits[t >> 4];
15437 		buf[i*2 + 1] = duk_lc_digits[t & 0x0f];
15438 	}
15439 #endif  /* DUK_USE_HEX_FASTPATH */
15440 
15441 	/* XXX: Using a string return value forces a string intern which is
15442 	 * not always necessary.  As a rough performance measure, hex encode
15443 	 * time for tests/perf/test-hex-encode.js dropped from ~35s to ~15s
15444 	 * without string coercion.  Change to returning a buffer and let the
15445 	 * caller coerce to string if necessary?
15446 	 */
15447 
15448 	ret = duk_buffer_to_string(thr, -1);  /* Safe, result is ASCII. */
15449 	duk_replace(thr, idx);
15450 	return ret;
15451 }
15452 
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15453 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15454 	const duk_uint8_t *inp;
15455 	duk_size_t len;
15456 	duk_size_t i;
15457 	duk_int_t t;
15458 	duk_uint8_t *buf;
15459 #if defined(DUK_USE_HEX_FASTPATH)
15460 	duk_int_t chk;
15461 	duk_uint8_t *p;
15462 	duk_size_t len_safe;
15463 #endif
15464 
15465 	DUK_ASSERT_API_ENTRY(thr);
15466 
15467 	idx = duk_require_normalize_index(thr, idx);
15468 	inp = duk__prep_codec_arg(thr, idx, &len);
15469 	DUK_ASSERT(inp != NULL || len == 0);
15470 
15471 	if (len & 0x01) {
15472 		goto type_error;
15473 	}
15474 
15475 	/* Fixed buffer, no zeroing because we'll fill all the data. */
15476 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len / 2);
15477 	DUK_ASSERT(buf != NULL);
15478 
15479 #if defined(DUK_USE_HEX_FASTPATH)
15480 	p = buf;
15481 	len_safe = len & ~0x07U;
15482 	for (i = 0; i < len_safe; i += 8) {
15483 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i]]) |
15484 		    ((duk_int_t) duk_hex_dectab[inp[i + 1]]);
15485 		chk = t;
15486 		p[0] = (duk_uint8_t) t;
15487 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 2]]) |
15488 		    ((duk_int_t) duk_hex_dectab[inp[i + 3]]);
15489 		chk |= t;
15490 		p[1] = (duk_uint8_t) t;
15491 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 4]]) |
15492 		    ((duk_int_t) duk_hex_dectab[inp[i + 5]]);
15493 		chk |= t;
15494 		p[2] = (duk_uint8_t) t;
15495 		t = ((duk_int_t) duk_hex_dectab_shift4[inp[i + 6]]) |
15496 		    ((duk_int_t) duk_hex_dectab[inp[i + 7]]);
15497 		chk |= t;
15498 		p[3] = (duk_uint8_t) t;
15499 		p += 4;
15500 
15501 		/* Check if any lookup above had a negative result. */
15502 		if (DUK_UNLIKELY(chk < 0)) {
15503 			goto type_error;
15504 		}
15505 	}
15506 	for (; i < len; i += 2) {
15507 		/* First cast to duk_int_t to sign extend, second cast to
15508 		 * duk_uint_t to avoid signed left shift, and final cast to
15509 		 * duk_int_t result type.
15510 		 */
15511 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15512 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15513 		if (DUK_UNLIKELY(t < 0)) {
15514 			goto type_error;
15515 		}
15516 		*p++ = (duk_uint8_t) t;
15517 	}
15518 #else  /* DUK_USE_HEX_FASTPATH */
15519 	for (i = 0; i < len; i += 2) {
15520 		/* For invalid characters the value -1 gets extended to
15521 		 * at least 16 bits.  If either nybble is invalid, the
15522 		 * resulting 't' will be < 0.
15523 		 */
15524 		t = (duk_int_t) ((((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i]]) << 4U) |
15525 		                 ((duk_uint_t) (duk_int_t) duk_hex_dectab[inp[i + 1]]));
15526 		if (DUK_UNLIKELY(t < 0)) {
15527 			goto type_error;
15528 		}
15529 		buf[i >> 1] = (duk_uint8_t) t;
15530 	}
15531 #endif  /* DUK_USE_HEX_FASTPATH */
15532 
15533 	duk_replace(thr, idx);
15534 	return;
15535 
15536  type_error:
15537 	DUK_ERROR_TYPE(thr, DUK_STR_HEX_DECODE_FAILED);
15538 	DUK_WO_NORETURN(return;);
15539 }
15540 #else  /* DUK_USE_HEX_SUPPORT */
duk_hex_encode(duk_hthread * thr,duk_idx_t idx)15541 DUK_EXTERNAL const char *duk_hex_encode(duk_hthread *thr, duk_idx_t idx) {
15542 	DUK_UNREF(idx);
15543 	DUK_ERROR_UNSUPPORTED(thr);
15544 	DUK_WO_NORETURN(return;);
15545 }
duk_hex_decode(duk_hthread * thr,duk_idx_t idx)15546 DUK_EXTERNAL void duk_hex_decode(duk_hthread *thr, duk_idx_t idx) {
15547 	DUK_UNREF(idx);
15548 	DUK_ERROR_UNSUPPORTED(thr);
15549 	DUK_WO_NORETURN(return;);
15550 }
15551 #endif  /* DUK_USE_HEX_SUPPORT */
15552 
15553 /*
15554  *  JSON
15555  */
15556 
15557 #if defined(DUK_USE_JSON_SUPPORT)
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15558 DUK_EXTERNAL const char *duk_json_encode(duk_hthread *thr, duk_idx_t idx) {
15559 #if defined(DUK_USE_ASSERTIONS)
15560 	duk_idx_t top_at_entry;
15561 #endif
15562 	const char *ret;
15563 
15564 	DUK_ASSERT_API_ENTRY(thr);
15565 #if defined(DUK_USE_ASSERTIONS)
15566 	top_at_entry = duk_get_top(thr);
15567 #endif
15568 
15569 	idx = duk_require_normalize_index(thr, idx);
15570 	duk_bi_json_stringify_helper(thr,
15571 	                             idx /*idx_value*/,
15572 	                             DUK_INVALID_INDEX /*idx_replacer*/,
15573 	                             DUK_INVALID_INDEX /*idx_space*/,
15574 	                             0 /*flags*/);
15575 	DUK_ASSERT(duk_is_string(thr, -1));
15576 	duk_replace(thr, idx);
15577 	ret = duk_get_string(thr, idx);
15578 
15579 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15580 
15581 	return ret;
15582 }
15583 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15584 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15585 #if defined(DUK_USE_ASSERTIONS)
15586 	duk_idx_t top_at_entry;
15587 #endif
15588 
15589 	DUK_ASSERT_API_ENTRY(thr);
15590 #if defined(DUK_USE_ASSERTIONS)
15591 	top_at_entry = duk_get_top(thr);
15592 #endif
15593 
15594 	idx = duk_require_normalize_index(thr, idx);
15595 	duk_bi_json_parse_helper(thr,
15596 	                         idx /*idx_value*/,
15597 	                         DUK_INVALID_INDEX /*idx_reviver*/,
15598 	                         0 /*flags*/);
15599 	duk_replace(thr, idx);
15600 
15601 	DUK_ASSERT(duk_get_top(thr) == top_at_entry);
15602 }
15603 #else  /* DUK_USE_JSON_SUPPORT */
duk_json_encode(duk_hthread * thr,duk_idx_t idx)15604 DUK_EXTERNAL const char *duk_json_encode(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 NULL;);
15609 }
15610 
duk_json_decode(duk_hthread * thr,duk_idx_t idx)15611 DUK_EXTERNAL void duk_json_decode(duk_hthread *thr, duk_idx_t idx) {
15612 	DUK_ASSERT_API_ENTRY(thr);
15613 	DUK_UNREF(idx);
15614 	DUK_ERROR_UNSUPPORTED(thr);
15615 	DUK_WO_NORETURN(return;);
15616 }
15617 #endif  /* DUK_USE_JSON_SUPPORT */
15618 #line 1 "duk_api_compile.c"
15619 /*
15620  *  Compilation and evaluation
15621  */
15622 
15623 /* #include duk_internal.h -> already included */
15624 
15625 typedef struct duk__compile_raw_args duk__compile_raw_args;
15626 struct duk__compile_raw_args {
15627 	duk_size_t src_length;  /* should be first on 64-bit platforms */
15628 	const duk_uint8_t *src_buffer;
15629 	duk_uint_t flags;
15630 };
15631 
15632 /* 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)15633 DUK_EXTERNAL duk_int_t duk_eval_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15634 	duk_int_t rc;
15635 
15636 	DUK_ASSERT_API_ENTRY(thr);
15637 
15638 	/* Note: strictness is *not* inherited from the current Duktape/C.
15639 	 * This would be confusing because the current strictness state
15640 	 * depends on whether we're running inside a Duktape/C activation
15641 	 * (= strict mode) or outside of any activation (= non-strict mode).
15642 	 * See tests/api/test-eval-strictness.c for more discussion.
15643 	 */
15644 
15645 	/* [ ... source? filename? ] (depends on flags) */
15646 
15647 	rc = duk_compile_raw(thr, src_buffer, src_length, flags | DUK_COMPILE_EVAL);  /* may be safe, or non-safe depending on flags */
15648 
15649 	/* [ ... closure/error ] */
15650 
15651 	if (rc != DUK_EXEC_SUCCESS) {
15652 		rc = DUK_EXEC_ERROR;
15653 		goto got_rc;
15654 	}
15655 
15656 	duk_push_global_object(thr);  /* explicit 'this' binding, see GH-164 */
15657 
15658 	if (flags & DUK_COMPILE_SAFE) {
15659 		rc = duk_pcall_method(thr, 0);
15660 	} else {
15661 		duk_call_method(thr, 0);
15662 		rc = DUK_EXEC_SUCCESS;
15663 	}
15664 
15665 	/* [ ... result/error ] */
15666 
15667  got_rc:
15668 	if (flags & DUK_COMPILE_NORESULT) {
15669 		duk_pop(thr);
15670 	}
15671 
15672 	return rc;
15673 }
15674 
15675 /* Helper which can be called both directly and with duk_safe_call(). */
duk__do_compile(duk_hthread * thr,void * udata)15676 DUK_LOCAL duk_ret_t duk__do_compile(duk_hthread *thr, void *udata) {
15677 	duk__compile_raw_args *comp_args;
15678 	duk_uint_t flags;
15679 	duk_hcompfunc *h_templ;
15680 
15681 	DUK_ASSERT_CTX_VALID(thr);
15682 	DUK_ASSERT(udata != NULL);
15683 
15684 	/* Note: strictness is not inherited from the current Duktape/C
15685 	 * context.  Otherwise it would not be possible to compile
15686 	 * non-strict code inside a Duktape/C activation (which is
15687 	 * always strict now).  See tests/api/test-eval-strictness.c
15688 	 * for discussion.
15689 	 */
15690 
15691 	/* [ ... source? filename? ] (depends on flags) */
15692 
15693 	comp_args = (duk__compile_raw_args *) udata;
15694 	flags = comp_args->flags;
15695 
15696 	if (flags & DUK_COMPILE_NOFILENAME) {
15697 		/* Automatic filename: 'eval' or 'input'. */
15698 		duk_push_hstring_stridx(thr, (flags & DUK_COMPILE_EVAL) ? DUK_STRIDX_EVAL : DUK_STRIDX_INPUT);
15699 	}
15700 
15701 	/* [ ... source? filename ] */
15702 
15703 	if (!comp_args->src_buffer) {
15704 		duk_hstring *h_sourcecode;
15705 
15706 		h_sourcecode = duk_get_hstring(thr, -2);
15707 		if ((flags & DUK_COMPILE_NOSOURCE) ||  /* args incorrect */
15708 		    (h_sourcecode == NULL)) {          /* e.g. duk_push_string_file_raw() pushed undefined */
15709 			DUK_ERROR_TYPE(thr, DUK_STR_NO_SOURCECODE);
15710 			DUK_WO_NORETURN(return 0;);
15711 		}
15712 		DUK_ASSERT(h_sourcecode != NULL);
15713 		comp_args->src_buffer = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode);
15714 		comp_args->src_length = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode);
15715 	}
15716 	DUK_ASSERT(comp_args->src_buffer != NULL);
15717 
15718 	if (flags & DUK_COMPILE_FUNCTION) {
15719 		flags |= DUK_COMPILE_EVAL | DUK_COMPILE_FUNCEXPR;
15720 	}
15721 
15722 	/* [ ... source? filename ] */
15723 
15724 	duk_js_compile(thr, comp_args->src_buffer, comp_args->src_length, flags);
15725 
15726 	/* [ ... source? func_template ] */
15727 
15728 	if (flags & DUK_COMPILE_NOSOURCE) {
15729 		;
15730 	} else {
15731 		duk_remove_m2(thr);
15732 	}
15733 
15734 	/* [ ... func_template ] */
15735 
15736 	h_templ = (duk_hcompfunc *) duk_known_hobject(thr, -1);
15737 	duk_js_push_closure(thr,
15738 	                   h_templ,
15739 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15740 	                   thr->builtins[DUK_BIDX_GLOBAL_ENV],
15741 	                   1 /*add_auto_proto*/);
15742 	duk_remove_m2(thr);   /* -> [ ... closure ] */
15743 
15744 	/* [ ... closure ] */
15745 
15746 	return 1;
15747 }
15748 
duk_compile_raw(duk_hthread * thr,const char * src_buffer,duk_size_t src_length,duk_uint_t flags)15749 DUK_EXTERNAL duk_int_t duk_compile_raw(duk_hthread *thr, const char *src_buffer, duk_size_t src_length, duk_uint_t flags) {
15750 	duk__compile_raw_args comp_args_alloc;
15751 	duk__compile_raw_args *comp_args = &comp_args_alloc;
15752 
15753 	DUK_ASSERT_API_ENTRY(thr);
15754 
15755 	if ((flags & DUK_COMPILE_STRLEN) && (src_buffer != NULL)) {
15756 		/* String length is computed here to avoid multiple evaluation
15757 		 * of a macro argument in the calling side.
15758 		 */
15759 		src_length = DUK_STRLEN(src_buffer);
15760 	}
15761 
15762 	comp_args->src_buffer = (const duk_uint8_t *) src_buffer;
15763 	comp_args->src_length = src_length;
15764 	comp_args->flags = flags;
15765 
15766 	/* [ ... source? filename? ] (depends on flags) */
15767 
15768 	if (flags & DUK_COMPILE_SAFE) {
15769 		duk_int_t rc;
15770 		duk_int_t nargs;
15771 		duk_int_t nrets = 1;
15772 
15773 		/* Arguments can be: [ source? filename? &comp_args] so that
15774 		 * nargs is 1 to 3.  Call site encodes the correct nargs count
15775 		 * directly into flags.
15776 		 */
15777 		nargs = flags & 0x07;
15778 		DUK_ASSERT(nargs == ((flags & DUK_COMPILE_NOSOURCE) ? 0 : 1) +
15779 		                    ((flags & DUK_COMPILE_NOFILENAME) ? 0 : 1));
15780 		rc = duk_safe_call(thr, duk__do_compile, (void *) comp_args, nargs, nrets);
15781 
15782 		/* [ ... closure ] */
15783 		return rc;
15784 	}
15785 
15786 	(void) duk__do_compile(thr, (void *) comp_args);
15787 
15788 	/* [ ... closure ] */
15789 	return DUK_EXEC_SUCCESS;
15790 }
15791 #line 1 "duk_api_debug.c"
15792 /*
15793  *  Debugging related API calls
15794  */
15795 
15796 /* #include duk_internal.h -> already included */
15797 
15798 #if defined(DUK_USE_JSON_SUPPORT)
duk_push_context_dump(duk_hthread * thr)15799 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15800 	duk_idx_t idx;
15801 	duk_idx_t top;
15802 
15803 	DUK_ASSERT_API_ENTRY(thr);
15804 
15805 	/* We don't duk_require_stack() here now, but rely on the caller having
15806 	 * enough space.
15807 	 */
15808 
15809 	top = duk_get_top(thr);
15810 	duk_push_array(thr);
15811 	for (idx = 0; idx < top; idx++) {
15812 		duk_dup(thr, idx);
15813 		duk_put_prop_index(thr, -2, (duk_uarridx_t) idx);
15814 	}
15815 
15816 	/* XXX: conversion errors should not propagate outwards.
15817 	 * Perhaps values need to be coerced individually?
15818 	 */
15819 	duk_bi_json_stringify_helper(thr,
15820 	                             duk_get_top_index(thr),  /*idx_value*/
15821 	                             DUK_INVALID_INDEX,  /*idx_replacer*/
15822 	                             DUK_INVALID_INDEX,  /*idx_space*/
15823 	                             DUK_JSON_FLAG_EXT_CUSTOM |
15824 	                             DUK_JSON_FLAG_ASCII_ONLY |
15825 	                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
15826 
15827 	duk_push_sprintf(thr, "ctx: top=%ld, stack=%s", (long) top, (const char *) duk_safe_to_string(thr, -1));
15828 	duk_replace(thr, -3);  /* [ ... arr jsonx(arr) res ] -> [ ... res jsonx(arr) ] */
15829 	duk_pop(thr);
15830 	DUK_ASSERT(duk_is_string(thr, -1));
15831 }
15832 #else  /* DUK_USE_JSON_SUPPORT */
duk_push_context_dump(duk_hthread * thr)15833 DUK_EXTERNAL void duk_push_context_dump(duk_hthread *thr) {
15834 	DUK_ASSERT_API_ENTRY(thr);
15835 	DUK_ERROR_UNSUPPORTED(thr);
15836 	DUK_WO_NORETURN(return;);
15837 }
15838 #endif  /* DUK_USE_JSON_SUPPORT */
15839 
15840 #if defined(DUK_USE_DEBUGGER_SUPPORT)
15841 
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)15842 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
15843                                       duk_debug_read_function read_cb,
15844                                       duk_debug_write_function write_cb,
15845                                       duk_debug_peek_function peek_cb,
15846                                       duk_debug_read_flush_function read_flush_cb,
15847                                       duk_debug_write_flush_function write_flush_cb,
15848                                       duk_debug_request_function request_cb,
15849                                       duk_debug_detached_function detached_cb,
15850                                       void *udata) {
15851 	duk_heap *heap;
15852 	const char *str;
15853 	duk_size_t len;
15854 
15855 	/* XXX: should there be an error or an automatic detach if
15856 	 * already attached?
15857 	 */
15858 
15859 	DUK_D(DUK_DPRINT("application called duk_debugger_attach()"));
15860 
15861 	DUK_ASSERT_API_ENTRY(thr);
15862 	DUK_ASSERT(read_cb != NULL);
15863 	DUK_ASSERT(write_cb != NULL);
15864 	/* Other callbacks are optional. */
15865 
15866 	heap = thr->heap;
15867 	heap->dbg_read_cb = read_cb;
15868 	heap->dbg_write_cb = write_cb;
15869 	heap->dbg_peek_cb = peek_cb;
15870 	heap->dbg_read_flush_cb = read_flush_cb;
15871 	heap->dbg_write_flush_cb = write_flush_cb;
15872 	heap->dbg_request_cb = request_cb;
15873 	heap->dbg_detached_cb = detached_cb;
15874 	heap->dbg_udata = udata;
15875 	heap->dbg_have_next_byte = 0;
15876 
15877 	/* Start in paused state. */
15878 	heap->dbg_processing = 0;
15879 	heap->dbg_state_dirty = 0;
15880 	heap->dbg_force_restart = 0;
15881 	heap->dbg_pause_flags = 0;
15882 	heap->dbg_pause_act = NULL;
15883 	heap->dbg_pause_startline = 0;
15884 	heap->dbg_exec_counter = 0;
15885 	heap->dbg_last_counter = 0;
15886 	heap->dbg_last_time = 0.0;
15887 	duk_debug_set_paused(heap);  /* XXX: overlap with fields above */
15888 
15889 	/* Send version identification and flush right afterwards.  Note that
15890 	 * we must write raw, unframed bytes here.
15891 	 */
15892 	duk_push_sprintf(thr, "%ld %ld %s %s\n",
15893 	                 (long) DUK_DEBUG_PROTOCOL_VERSION,
15894 	                 (long) DUK_VERSION,
15895 	                 (const char *) DUK_GIT_DESCRIBE,
15896 	                 (const char *) DUK_USE_TARGET_INFO);
15897 	str = duk_get_lstring(thr, -1, &len);
15898 	DUK_ASSERT(str != NULL);
15899 	duk_debug_write_bytes(thr, (const duk_uint8_t *) str, len);
15900 	duk_debug_write_flush(thr);
15901 	duk_pop(thr);
15902 }
15903 
duk_debugger_detach(duk_hthread * thr)15904 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
15905 	DUK_D(DUK_DPRINT("application called duk_debugger_detach()"));
15906 
15907 	DUK_ASSERT_API_ENTRY(thr);
15908 	DUK_ASSERT(thr->heap != NULL);
15909 
15910 	/* Can be called multiple times with no harm. */
15911 	duk_debug_do_detach(thr->heap);
15912 }
15913 
duk_debugger_cooperate(duk_hthread * thr)15914 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
15915 	duk_bool_t processed_messages;
15916 
15917 	DUK_ASSERT_API_ENTRY(thr);
15918 	DUK_ASSERT(thr->heap != NULL);
15919 
15920 	if (!duk_debug_is_attached(thr->heap)) {
15921 		return;
15922 	}
15923 	if (thr->callstack_curr != NULL || thr->heap->dbg_processing) {
15924 		/* Calling duk_debugger_cooperate() while Duktape is being
15925 		 * called into is not supported.  This is not a 100% check
15926 		 * but prevents any damage in most cases.
15927 		 */
15928 		return;
15929 	}
15930 
15931 	processed_messages = duk_debug_process_messages(thr, 1 /*no_block*/);
15932 	DUK_UNREF(processed_messages);
15933 }
15934 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)15935 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
15936 	duk_idx_t top;
15937 	duk_idx_t idx;
15938 	duk_bool_t ret = 0;
15939 
15940 	DUK_ASSERT_API_ENTRY(thr);
15941 	DUK_ASSERT(thr->heap != NULL);
15942 
15943 	DUK_D(DUK_DPRINT("application called duk_debugger_notify() with nvalues=%ld", (long) nvalues));
15944 
15945 	top = duk_get_top(thr);
15946 	if (top < nvalues) {
15947 		DUK_ERROR_RANGE(thr, "not enough stack values for notify");
15948 		DUK_WO_NORETURN(return 0;);
15949 	}
15950 	if (duk_debug_is_attached(thr->heap)) {
15951 		duk_debug_write_notify(thr, DUK_DBG_CMD_APPNOTIFY);
15952 		for (idx = top - nvalues; idx < top; idx++) {
15953 			duk_tval *tv = DUK_GET_TVAL_POSIDX(thr, idx);
15954 			duk_debug_write_tval(thr, tv);
15955 		}
15956 		duk_debug_write_eom(thr);
15957 
15958 		/* Return non-zero (true) if we have a good reason to believe
15959 		 * the notify was delivered; if we're still attached at least
15960 		 * a transport error was not indicated by the transport write
15961 		 * callback.  This is not a 100% guarantee of course.
15962 		 */
15963 		if (duk_debug_is_attached(thr->heap)) {
15964 			ret = 1;
15965 		}
15966 	}
15967 	duk_pop_n(thr, nvalues);
15968 	return ret;
15969 }
15970 
duk_debugger_pause(duk_hthread * thr)15971 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
15972 	DUK_ASSERT_API_ENTRY(thr);
15973 	DUK_ASSERT(thr->heap != NULL);
15974 
15975 	DUK_D(DUK_DPRINT("application called duk_debugger_pause()"));
15976 
15977 	/* Treat like a debugger statement: ignore when not attached. */
15978 	if (duk_debug_is_attached(thr->heap)) {
15979 		if (duk_debug_is_paused(thr->heap)) {
15980 			DUK_D(DUK_DPRINT("duk_debugger_pause() called when already paused; ignoring"));
15981 		} else {
15982 			duk_debug_set_paused(thr->heap);
15983 
15984 			/* Pause on the next opcode executed.  This is always safe to do even
15985 			 * inside the debugger message loop: the interrupt counter will be reset
15986 			 * to its proper value when the message loop exits.
15987 			 */
15988 			thr->interrupt_init = 1;
15989 			thr->interrupt_counter = 0;
15990 		}
15991 	}
15992 }
15993 
15994 #else  /* DUK_USE_DEBUGGER_SUPPORT */
15995 
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)15996 DUK_EXTERNAL void duk_debugger_attach(duk_hthread *thr,
15997                                       duk_debug_read_function read_cb,
15998                                       duk_debug_write_function write_cb,
15999                                       duk_debug_peek_function peek_cb,
16000                                       duk_debug_read_flush_function read_flush_cb,
16001                                       duk_debug_write_flush_function write_flush_cb,
16002                                       duk_debug_request_function request_cb,
16003                                       duk_debug_detached_function detached_cb,
16004                                       void *udata) {
16005 	DUK_ASSERT_API_ENTRY(thr);
16006 	DUK_UNREF(read_cb);
16007 	DUK_UNREF(write_cb);
16008 	DUK_UNREF(peek_cb);
16009 	DUK_UNREF(read_flush_cb);
16010 	DUK_UNREF(write_flush_cb);
16011 	DUK_UNREF(request_cb);
16012 	DUK_UNREF(detached_cb);
16013 	DUK_UNREF(udata);
16014 	DUK_ERROR_TYPE(thr, "no debugger support");
16015 	DUK_WO_NORETURN(return;);
16016 }
16017 
duk_debugger_detach(duk_hthread * thr)16018 DUK_EXTERNAL void duk_debugger_detach(duk_hthread *thr) {
16019 	DUK_ASSERT_API_ENTRY(thr);
16020 	DUK_ERROR_TYPE(thr, "no debugger support");
16021 	DUK_WO_NORETURN(return;);
16022 }
16023 
duk_debugger_cooperate(duk_hthread * thr)16024 DUK_EXTERNAL void duk_debugger_cooperate(duk_hthread *thr) {
16025 	/* nop */
16026 	DUK_ASSERT_API_ENTRY(thr);
16027 	DUK_UNREF(thr);
16028 }
16029 
duk_debugger_notify(duk_hthread * thr,duk_idx_t nvalues)16030 DUK_EXTERNAL duk_bool_t duk_debugger_notify(duk_hthread *thr, duk_idx_t nvalues) {
16031 	duk_idx_t top;
16032 
16033 	DUK_ASSERT_API_ENTRY(thr);
16034 
16035 	top = duk_get_top(thr);
16036 	if (top < nvalues) {
16037 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
16038 		DUK_WO_NORETURN(return 0;);
16039 	}
16040 
16041 	/* No debugger support, just pop values. */
16042 	duk_pop_n(thr, nvalues);
16043 	return 0;
16044 }
16045 
duk_debugger_pause(duk_hthread * thr)16046 DUK_EXTERNAL void duk_debugger_pause(duk_hthread *thr) {
16047 	/* Treat like debugger statement: nop */
16048 	DUK_ASSERT_API_ENTRY(thr);
16049 	DUK_UNREF(thr);
16050 }
16051 
16052 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
16053 #line 1 "duk_api_heap.c"
16054 /*
16055  *  Heap creation and destruction
16056  */
16057 
16058 /* #include duk_internal.h -> already included */
16059 
16060 typedef struct duk_internal_thread_state duk_internal_thread_state;
16061 
16062 struct duk_internal_thread_state {
16063 	duk_ljstate lj;
16064 	duk_bool_t creating_error;
16065 	duk_hthread *curr_thread;
16066 	duk_int_t call_recursion_depth;
16067 };
16068 
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)16069 DUK_EXTERNAL duk_hthread *duk_create_heap(duk_alloc_function alloc_func,
16070                                           duk_realloc_function realloc_func,
16071                                           duk_free_function free_func,
16072                                           void *heap_udata,
16073                                           duk_fatal_function fatal_handler) {
16074 	duk_heap *heap = NULL;
16075 	duk_hthread *thr;
16076 
16077 	/* Assume that either all memory funcs are NULL or non-NULL, mixed
16078 	 * cases will now be unsafe.
16079 	 */
16080 
16081 	/* XXX: just assert non-NULL values here and make caller arguments
16082 	 * do the defaulting to the default implementations (smaller code)?
16083 	 */
16084 
16085 	if (!alloc_func) {
16086 		DUK_ASSERT(realloc_func == NULL);
16087 		DUK_ASSERT(free_func == NULL);
16088 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
16089 		alloc_func = duk_default_alloc_function;
16090 		realloc_func = duk_default_realloc_function;
16091 		free_func = duk_default_free_function;
16092 #else
16093 		DUK_D(DUK_DPRINT("no allocation functions given and no default providers"));
16094 		return NULL;
16095 #endif
16096 	} else {
16097 		DUK_ASSERT(realloc_func != NULL);
16098 		DUK_ASSERT(free_func != NULL);
16099 	}
16100 
16101 	if (!fatal_handler) {
16102 		fatal_handler = duk_default_fatal_handler;
16103 	}
16104 
16105 	DUK_ASSERT(alloc_func != NULL);
16106 	DUK_ASSERT(realloc_func != NULL);
16107 	DUK_ASSERT(free_func != NULL);
16108 	DUK_ASSERT(fatal_handler != NULL);
16109 
16110 	heap = duk_heap_alloc(alloc_func, realloc_func, free_func, heap_udata, fatal_handler);
16111 	if (!heap) {
16112 		return NULL;
16113 	}
16114 	thr = heap->heap_thread;
16115 	DUK_ASSERT(thr != NULL);
16116 	DUK_ASSERT(thr->heap != NULL);
16117 	return thr;
16118 }
16119 
duk_destroy_heap(duk_hthread * thr)16120 DUK_EXTERNAL void duk_destroy_heap(duk_hthread *thr) {
16121 	duk_heap *heap;
16122 
16123 	if (!thr) {
16124 		return;
16125 	}
16126 	DUK_ASSERT_API_ENTRY(thr);
16127 	heap = thr->heap;
16128 	DUK_ASSERT(heap != NULL);
16129 
16130 	duk_heap_free(heap);
16131 }
16132 
duk_suspend(duk_hthread * thr,duk_thread_state * state)16133 DUK_EXTERNAL void duk_suspend(duk_hthread *thr, duk_thread_state *state) {
16134 	duk_internal_thread_state *snapshot = (duk_internal_thread_state *) (void *) state;
16135 	duk_heap *heap;
16136 	duk_ljstate *lj;
16137 
16138 	DUK_ASSERT_API_ENTRY(thr);
16139 	DUK_ASSERT(thr->heap != NULL);
16140 	DUK_ASSERT(state != NULL);  /* unvalidated */
16141 
16142 	/* Currently not supported when called from within a finalizer.
16143 	 * If that is done, the finalizer will remain running indefinitely,
16144 	 * preventing other finalizers from executing.  The assert is a bit
16145 	 * wider, checking that it would be OK to run pending finalizers.
16146 	 */
16147 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16148 
16149 	/* Currently not supported to duk_suspend() from an errCreate()
16150 	 * call.
16151 	 */
16152 	DUK_ASSERT(thr->heap->creating_error == 0);
16153 
16154 	heap = thr->heap;
16155 	lj = &heap->lj;
16156 
16157 	duk_push_tval(thr, &lj->value1);
16158 	duk_push_tval(thr, &lj->value2);
16159 
16160 	/* XXX: creating_error == 0 is asserted above, so no need to store. */
16161 	duk_memcpy((void *) &snapshot->lj, (const void *) lj, sizeof(duk_ljstate));
16162 	snapshot->creating_error = heap->creating_error;
16163 	snapshot->curr_thread = heap->curr_thread;
16164 	snapshot->call_recursion_depth = heap->call_recursion_depth;
16165 
16166 	lj->jmpbuf_ptr = NULL;
16167 	lj->type = DUK_LJ_TYPE_UNKNOWN;
16168 	DUK_TVAL_SET_UNDEFINED(&lj->value1);
16169 	DUK_TVAL_SET_UNDEFINED(&lj->value2);
16170 	heap->creating_error = 0;
16171 	heap->curr_thread = NULL;
16172 	heap->call_recursion_depth = 0;
16173 }
16174 
duk_resume(duk_hthread * thr,const duk_thread_state * state)16175 DUK_EXTERNAL void duk_resume(duk_hthread *thr, const duk_thread_state *state) {
16176 	const duk_internal_thread_state *snapshot = (const duk_internal_thread_state *) (const void *) state;
16177 	duk_heap *heap;
16178 
16179 	DUK_ASSERT_API_ENTRY(thr);
16180 	DUK_ASSERT(thr->heap != NULL);
16181 	DUK_ASSERT(state != NULL);  /* unvalidated */
16182 
16183 	/* Shouldn't be necessary if duk_suspend() is called before
16184 	 * duk_resume(), but assert in case API sequence is incorrect.
16185 	 */
16186 	DUK_ASSERT(thr->heap->pf_prevent_count == 0);
16187 	DUK_ASSERT(thr->heap->creating_error == 0);
16188 
16189 	heap = thr->heap;
16190 
16191 	duk_memcpy((void *) &heap->lj, (const void *) &snapshot->lj, sizeof(duk_ljstate));
16192 	heap->creating_error = snapshot->creating_error;
16193 	heap->curr_thread = snapshot->curr_thread;
16194 	heap->call_recursion_depth = snapshot->call_recursion_depth;
16195 
16196 	duk_pop_2(thr);
16197 }
16198 
16199 /* XXX: better place for this */
duk_set_global_object(duk_hthread * thr)16200 DUK_EXTERNAL void duk_set_global_object(duk_hthread *thr) {
16201 	duk_hobject *h_glob;
16202 	duk_hobject *h_prev_glob;
16203 	duk_hobjenv *h_env;
16204 	duk_hobject *h_prev_env;
16205 
16206 	DUK_ASSERT_API_ENTRY(thr);
16207 
16208 	DUK_D(DUK_DPRINT("replace global object with: %!T", duk_get_tval(thr, -1)));
16209 
16210 	h_glob = duk_require_hobject(thr, -1);
16211 	DUK_ASSERT(h_glob != NULL);
16212 
16213 	/*
16214 	 *  Replace global object.
16215 	 */
16216 
16217 	h_prev_glob = thr->builtins[DUK_BIDX_GLOBAL];
16218 	DUK_UNREF(h_prev_glob);
16219 	thr->builtins[DUK_BIDX_GLOBAL] = h_glob;
16220 	DUK_HOBJECT_INCREF(thr, h_glob);
16221 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_glob);  /* side effects, in theory (referenced by global env) */
16222 
16223 	/*
16224 	 *  Replace lexical environment for global scope
16225 	 *
16226 	 *  Create a new object environment for the global lexical scope.
16227 	 *  We can't just reset the _Target property of the current one,
16228 	 *  because the lexical scope is shared by other threads with the
16229 	 *  same (initial) built-ins.
16230 	 */
16231 
16232 	h_env = duk_hobjenv_alloc(thr,
16233 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
16234 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
16235 	DUK_ASSERT(h_env != NULL);
16236 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_env) == NULL);
16237 
16238 	DUK_ASSERT(h_env->target == NULL);
16239 	DUK_ASSERT(h_glob != NULL);
16240 	h_env->target = h_glob;
16241 	DUK_HOBJECT_INCREF(thr, h_glob);
16242 	DUK_ASSERT(h_env->has_this == 0);
16243 
16244 	/* [ ... new_glob ] */
16245 
16246 	h_prev_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
16247 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = (duk_hobject *) h_env;
16248 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_env);
16249 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, h_prev_env);  /* side effects */
16250 	DUK_UNREF(h_env);  /* without refcounts */
16251 	DUK_UNREF(h_prev_env);
16252 
16253 	/* [ ... new_glob ] */
16254 
16255 	duk_pop(thr);
16256 
16257 	/* [ ... ] */
16258 }
16259 #line 1 "duk_api_inspect.c"
16260 /*
16261  *  Inspection
16262  */
16263 
16264 /* #include duk_internal.h -> already included */
16265 
16266 /* For footprint efficient multiple value setting: arrays are much better than
16267  * varargs, format string with parsing is often better than string pointer arrays.
16268  */
duk__inspect_multiple_uint(duk_hthread * thr,const char * fmt,duk_int_t * vals)16269 DUK_LOCAL void duk__inspect_multiple_uint(duk_hthread *thr, const char *fmt, duk_int_t *vals) {
16270 	duk_int_t val;
16271 	const char *p;
16272 	const char *p_curr;
16273 	duk_size_t len;
16274 
16275 	for (p = fmt;;) {
16276 		len = DUK_STRLEN(p);
16277 		p_curr = p;
16278 		p += len + 1;
16279 		if (len == 0) {
16280 			/* Double NUL (= empty key) terminates. */
16281 			break;
16282 		}
16283 		val = *vals++;
16284 		if (val >= 0) {
16285 			/* Negative values are markers to skip key. */
16286 			duk_push_string(thr, p_curr);
16287 			duk_push_int(thr, val);
16288 			duk_put_prop(thr, -3);
16289 		}
16290 	}
16291 }
16292 
16293 /* Raw helper to extract internal information / statistics about a value.
16294  * The return value is an object with properties that are version specific.
16295  * The properties must not expose anything that would lead to security
16296  * issues (e.g. exposing compiled function 'data' buffer might be an issue).
16297  * Currently only counts and sizes and such are given so there shouldn't
16298  * be security implications.
16299  */
16300 
16301 #define DUK__IDX_TYPE     0
16302 #define DUK__IDX_ITAG     1
16303 #define DUK__IDX_REFC     2
16304 #define DUK__IDX_HBYTES   3
16305 #define DUK__IDX_CLASS    4
16306 #define DUK__IDX_PBYTES   5
16307 #define DUK__IDX_ESIZE    6
16308 #define DUK__IDX_ENEXT    7
16309 #define DUK__IDX_ASIZE    8
16310 #define DUK__IDX_HSIZE    9
16311 #define DUK__IDX_BCBYTES  10
16312 #define DUK__IDX_DBYTES   11
16313 #define DUK__IDX_TSTATE   12
16314 #define DUK__IDX_VARIANT  13
16315 
duk_inspect_value(duk_hthread * thr,duk_idx_t idx)16316 DUK_EXTERNAL void duk_inspect_value(duk_hthread *thr, duk_idx_t idx) {
16317 	duk_tval *tv;
16318 	duk_heaphdr *h;
16319 	/* The temporary values should be in an array rather than individual
16320 	 * variables which (in practice) ensures that the compiler won't map
16321 	 * them to registers and emit a lot of unnecessary shuffling code.
16322 	 */
16323 	duk_int_t vals[14];
16324 
16325 	DUK_ASSERT_API_ENTRY(thr);
16326 
16327 	/* Assume two's complement and set everything to -1. */
16328 	duk_memset((void *) &vals, (int) 0xff, sizeof(vals));
16329 	DUK_ASSERT(vals[DUK__IDX_TYPE] == -1);  /* spot check one */
16330 
16331 	tv = duk_get_tval_or_unused(thr, idx);
16332 	h = (DUK_TVAL_IS_HEAP_ALLOCATED(tv) ? DUK_TVAL_GET_HEAPHDR(tv) : NULL);
16333 
16334 	vals[DUK__IDX_TYPE] = duk_get_type_tval(tv);
16335 	vals[DUK__IDX_ITAG] = (duk_int_t) DUK_TVAL_GET_TAG(tv);
16336 
16337 	duk_push_bare_object(thr);  /* Invalidates 'tv'. */
16338 	tv = NULL;
16339 
16340 	if (h == NULL) {
16341 		goto finish;
16342 	}
16343 	duk_push_pointer(thr, (void *) h);
16344 	duk_put_prop_literal(thr, -2, "hptr");
16345 
16346 #if 0
16347 	/* Covers a lot of information, e.g. buffer and string variants. */
16348 	duk_push_uint(thr, (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
16349 	duk_put_prop_literal(thr, -2, "hflags");
16350 #endif
16351 
16352 #if defined(DUK_USE_REFERENCE_COUNTING)
16353 	vals[DUK__IDX_REFC] = (duk_int_t) DUK_HEAPHDR_GET_REFCOUNT(h);
16354 #endif
16355 	vals[DUK__IDX_VARIANT] = 0;
16356 
16357 	/* Heaphdr size and additional allocation size, followed by
16358 	 * type specific stuff (with varying value count).
16359 	 */
16360 	switch ((duk_small_int_t) DUK_HEAPHDR_GET_TYPE(h)) {
16361 	case DUK_HTYPE_STRING: {
16362 		duk_hstring *h_str = (duk_hstring *) h;
16363 		vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hstring) + DUK_HSTRING_GET_BYTELEN(h_str) + 1);
16364 #if defined(DUK_USE_HSTRING_EXTDATA)
16365 		if (DUK_HSTRING_HAS_EXTDATA(h_str)) {
16366 			vals[DUK__IDX_VARIANT] = 1;
16367 		}
16368 #endif
16369 		break;
16370 	}
16371 	case DUK_HTYPE_OBJECT: {
16372 		duk_hobject *h_obj = (duk_hobject *) h;
16373 
16374 		/* XXX: variants here are maybe pointless; class is enough? */
16375 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
16376 			vals[DUK__IDX_HBYTES] = sizeof(duk_harray);
16377 		} else if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16378 			vals[DUK__IDX_HBYTES] = sizeof(duk_hcompfunc);
16379 		} else if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
16380 			vals[DUK__IDX_HBYTES] = sizeof(duk_hnatfunc);
16381 		} else if (DUK_HOBJECT_IS_THREAD(h_obj)) {
16382 			vals[DUK__IDX_HBYTES] = sizeof(duk_hthread);
16383 			vals[DUK__IDX_TSTATE] = ((duk_hthread *) h_obj)->state;
16384 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
16385 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
16386 			vals[DUK__IDX_HBYTES] = sizeof(duk_hbufobj);
16387 			/* XXX: some size information */
16388 #endif
16389 		} else {
16390 			vals[DUK__IDX_HBYTES] = (duk_small_uint_t) sizeof(duk_hobject);
16391 		}
16392 
16393 		vals[DUK__IDX_CLASS] = (duk_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
16394 		vals[DUK__IDX_PBYTES] = (duk_int_t) DUK_HOBJECT_P_ALLOC_SIZE(h_obj);
16395 		vals[DUK__IDX_ESIZE] = (duk_int_t) DUK_HOBJECT_GET_ESIZE(h_obj);
16396 		vals[DUK__IDX_ENEXT] = (duk_int_t) DUK_HOBJECT_GET_ENEXT(h_obj);
16397 		vals[DUK__IDX_ASIZE] = (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj);
16398 		vals[DUK__IDX_HSIZE] = (duk_int_t) DUK_HOBJECT_GET_HSIZE(h_obj);
16399 
16400 		/* Note: e_next indicates the number of gc-reachable entries
16401 		 * in the entry part, and also indicates the index where the
16402 		 * next new property would be inserted.  It does *not* indicate
16403 		 * the number of non-NULL keys present in the object.  That
16404 		 * value could be counted separately but requires a pass through
16405 		 * the key list.
16406 		 */
16407 
16408 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
16409 			duk_hbuffer *h_data = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, (duk_hcompfunc *) h_obj);
16410 			vals[DUK__IDX_BCBYTES] = (duk_int_t) (h_data ? DUK_HBUFFER_GET_SIZE(h_data) : 0);
16411 		}
16412 		break;
16413 	}
16414 	case DUK_HTYPE_BUFFER: {
16415 		duk_hbuffer *h_buf = (duk_hbuffer *) h;
16416 
16417 		if (DUK_HBUFFER_HAS_DYNAMIC(h_buf)) {
16418 			if (DUK_HBUFFER_HAS_EXTERNAL(h_buf)) {
16419 				vals[DUK__IDX_VARIANT] = 2;  /* buffer variant 2: external */
16420 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_external));
16421 			} else {
16422 				/* When alloc_size == 0 the second allocation may not
16423 				 * actually exist.
16424 				 */
16425 				vals[DUK__IDX_VARIANT] = 1;  /* buffer variant 1: dynamic */
16426 				vals[DUK__IDX_HBYTES] = (duk_uint_t) (sizeof(duk_hbuffer_dynamic));
16427 			}
16428 			vals[DUK__IDX_DBYTES] = (duk_int_t) (DUK_HBUFFER_GET_SIZE(h_buf));
16429 		} else {
16430 			DUK_ASSERT(vals[DUK__IDX_VARIANT] == 0);  /* buffer variant 0: fixed */
16431 			vals[DUK__IDX_HBYTES] = (duk_int_t) (sizeof(duk_hbuffer_fixed) + DUK_HBUFFER_GET_SIZE(h_buf));
16432 		}
16433 		break;
16434 	}
16435 	}
16436 
16437  finish:
16438 	duk__inspect_multiple_uint(thr,
16439 	    "type" "\x00" "itag" "\x00" "refc" "\x00" "hbytes" "\x00" "class" "\x00"
16440 	    "pbytes" "\x00" "esize" "\x00" "enext" "\x00" "asize" "\x00" "hsize" "\x00"
16441 	    "bcbytes" "\x00" "dbytes" "\x00" "tstate" "\x00" "variant" "\x00" "\x00",
16442 	    (duk_int_t *) &vals);
16443 }
16444 
duk_inspect_callstack_entry(duk_hthread * thr,duk_int_t level)16445 DUK_EXTERNAL void duk_inspect_callstack_entry(duk_hthread *thr, duk_int_t level) {
16446 	duk_activation *act;
16447 	duk_uint_fast32_t pc;
16448 	duk_uint_fast32_t line;
16449 
16450 	DUK_ASSERT_API_ENTRY(thr);
16451 
16452 	/* -1   = top callstack entry
16453 	 * -2   = caller of level -1
16454 	 * etc
16455 	 */
16456 	act = duk_hthread_get_activation_for_level(thr, level);
16457 	if (act == NULL) {
16458 		duk_push_undefined(thr);
16459 		return;
16460 	}
16461 	duk_push_bare_object(thr);
16462 
16463 	/* Relevant PC is just before current one because PC is
16464 	 * post-incremented.  This should match what error augment
16465 	 * code does.
16466 	 */
16467 	pc = duk_hthread_get_act_prev_pc(thr, act);
16468 
16469 	duk_push_tval(thr, &act->tv_func);
16470 
16471 	duk_push_uint(thr, (duk_uint_t) pc);
16472 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_PC);
16473 
16474 #if defined(DUK_USE_PC2LINE)
16475 	line = duk_hobject_pc2line_query(thr, -1, pc);
16476 #else
16477 	line = 0;
16478 #endif
16479 	duk_push_uint(thr, (duk_uint_t) line);
16480 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_LINE_NUMBER);
16481 
16482 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_LC_FUNCTION);
16483 	/* Providing access to e.g. act->lex_env would be dangerous: these
16484 	 * internal structures must never be accessible to the application.
16485 	 * Duktape relies on them having consistent data, and this consistency
16486 	 * is only asserted for, not checked for.
16487 	 */
16488 }
16489 
16490 /* automatic undefs */
16491 #undef DUK__IDX_ASIZE
16492 #undef DUK__IDX_BCBYTES
16493 #undef DUK__IDX_CLASS
16494 #undef DUK__IDX_DBYTES
16495 #undef DUK__IDX_ENEXT
16496 #undef DUK__IDX_ESIZE
16497 #undef DUK__IDX_HBYTES
16498 #undef DUK__IDX_HSIZE
16499 #undef DUK__IDX_ITAG
16500 #undef DUK__IDX_PBYTES
16501 #undef DUK__IDX_REFC
16502 #undef DUK__IDX_TSTATE
16503 #undef DUK__IDX_TYPE
16504 #undef DUK__IDX_VARIANT
16505 #line 1 "duk_api_memory.c"
16506 /*
16507  *  Memory calls.
16508  */
16509 
16510 /* #include duk_internal.h -> already included */
16511 
duk_alloc_raw(duk_hthread * thr,duk_size_t size)16512 DUK_EXTERNAL void *duk_alloc_raw(duk_hthread *thr, duk_size_t size) {
16513 	DUK_ASSERT_API_ENTRY(thr);
16514 
16515 	return DUK_ALLOC_RAW(thr->heap, size);
16516 }
16517 
duk_free_raw(duk_hthread * thr,void * ptr)16518 DUK_EXTERNAL void duk_free_raw(duk_hthread *thr, void *ptr) {
16519 	DUK_ASSERT_API_ENTRY(thr);
16520 
16521 	DUK_FREE_RAW(thr->heap, ptr);
16522 }
16523 
duk_realloc_raw(duk_hthread * thr,void * ptr,duk_size_t size)16524 DUK_EXTERNAL void *duk_realloc_raw(duk_hthread *thr, void *ptr, duk_size_t size) {
16525 	DUK_ASSERT_API_ENTRY(thr);
16526 
16527 	return DUK_REALLOC_RAW(thr->heap, ptr, size);
16528 }
16529 
duk_alloc(duk_hthread * thr,duk_size_t size)16530 DUK_EXTERNAL void *duk_alloc(duk_hthread *thr, duk_size_t size) {
16531 	DUK_ASSERT_API_ENTRY(thr);
16532 
16533 	return DUK_ALLOC(thr->heap, size);
16534 }
16535 
duk_free(duk_hthread * thr,void * ptr)16536 DUK_EXTERNAL void duk_free(duk_hthread *thr, void *ptr) {
16537 	DUK_ASSERT_API_ENTRY(thr);
16538 
16539 	DUK_FREE_CHECKED(thr, ptr);
16540 }
16541 
duk_realloc(duk_hthread * thr,void * ptr,duk_size_t size)16542 DUK_EXTERNAL void *duk_realloc(duk_hthread *thr, void *ptr, duk_size_t size) {
16543 	DUK_ASSERT_API_ENTRY(thr);
16544 
16545 	/*
16546 	 *  Note: since this is an exposed API call, there should be
16547 	 *  no way a mark-and-sweep could have a side effect on the
16548 	 *  memory allocation behind 'ptr'; the pointer should never
16549 	 *  be something that Duktape wants to change.
16550 	 *
16551 	 *  Thus, no need to use DUK_REALLOC_INDIRECT (and we don't
16552 	 *  have the storage location here anyway).
16553 	 */
16554 
16555 	return DUK_REALLOC(thr->heap, ptr, size);
16556 }
16557 
duk_get_memory_functions(duk_hthread * thr,duk_memory_functions * out_funcs)16558 DUK_EXTERNAL void duk_get_memory_functions(duk_hthread *thr, duk_memory_functions *out_funcs) {
16559 	duk_heap *heap;
16560 
16561 	DUK_ASSERT_API_ENTRY(thr);
16562 	DUK_ASSERT(out_funcs != NULL);
16563 	DUK_ASSERT(thr != NULL);
16564 	DUK_ASSERT(thr->heap != NULL);
16565 
16566 	heap = thr->heap;
16567 	out_funcs->alloc_func = heap->alloc_func;
16568 	out_funcs->realloc_func = heap->realloc_func;
16569 	out_funcs->free_func = heap->free_func;
16570 	out_funcs->udata = heap->heap_udata;
16571 }
16572 
duk_gc(duk_hthread * thr,duk_uint_t flags)16573 DUK_EXTERNAL void duk_gc(duk_hthread *thr, duk_uint_t flags) {
16574 	duk_heap *heap;
16575 	duk_small_uint_t ms_flags;
16576 
16577 	DUK_ASSERT_API_ENTRY(thr);
16578 	heap = thr->heap;
16579 	DUK_ASSERT(heap != NULL);
16580 
16581 	DUK_D(DUK_DPRINT("mark-and-sweep requested by application"));
16582 	DUK_ASSERT(DUK_GC_COMPACT == DUK_MS_FLAG_EMERGENCY);  /* Compact flag is 1:1 with emergency flag which forces compaction. */
16583 	ms_flags = (duk_small_uint_t) flags;
16584 	duk_heap_mark_and_sweep(heap, ms_flags);
16585 }
16586 #line 1 "duk_api_object.c"
16587 /*
16588  *  Object handling: property access and other support functions.
16589  */
16590 
16591 /* #include duk_internal.h -> already included */
16592 
16593 /*
16594  *  Property handling
16595  *
16596  *  The API exposes only the most common property handling functions.
16597  *  The caller can invoke ECMAScript built-ins for full control (e.g.
16598  *  defineProperty, getOwnPropertyDescriptor).
16599  */
16600 
duk_get_prop(duk_hthread * thr,duk_idx_t obj_idx)16601 DUK_EXTERNAL duk_bool_t duk_get_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16602 	duk_tval *tv_obj;
16603 	duk_tval *tv_key;
16604 	duk_bool_t rc;
16605 
16606 	DUK_ASSERT_API_ENTRY(thr);
16607 
16608 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16609 	 * resize is not necessary for a property get right now.
16610 	 */
16611 
16612 	tv_obj = duk_require_tval(thr, obj_idx);
16613 	tv_key = duk_require_tval(thr, -1);
16614 
16615 	rc = duk_hobject_getprop(thr, tv_obj, tv_key);
16616 	DUK_ASSERT(rc == 0 || rc == 1);
16617 	/* a value is left on stack regardless of rc */
16618 
16619 	duk_remove_m2(thr);  /* remove key */
16620 	DUK_ASSERT(duk_is_undefined(thr, -1) || rc == 1);
16621 	return rc;  /* 1 if property found, 0 otherwise */
16622 }
16623 
duk_get_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16624 DUK_EXTERNAL duk_bool_t duk_get_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16625 	DUK_ASSERT_API_ENTRY(thr);
16626 	DUK_ASSERT(key != NULL);
16627 
16628 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16629 	(void) duk_push_string(thr, key);
16630 	return duk_get_prop(thr, obj_idx);
16631 }
16632 
duk_get_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16633 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) {
16634 	DUK_ASSERT_API_ENTRY(thr);
16635 	DUK_ASSERT(key != NULL);
16636 
16637 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16638 	(void) duk_push_lstring(thr, key, key_len);
16639 	return duk_get_prop(thr, obj_idx);
16640 }
16641 
16642 #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)16643 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) {
16644 	DUK_ASSERT_API_ENTRY(thr);
16645 	DUK_ASSERT(key != NULL);
16646 	DUK_ASSERT(key[key_len] == (char) 0);
16647 
16648 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16649 	(void) duk_push_literal_raw(thr, key, key_len);
16650 	return duk_get_prop(thr, obj_idx);
16651 }
16652 #endif
16653 
duk_get_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16654 DUK_EXTERNAL duk_bool_t duk_get_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16655 	DUK_ASSERT_API_ENTRY(thr);
16656 
16657 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16658 	duk_push_uarridx(thr, arr_idx);
16659 	return duk_get_prop(thr, obj_idx);
16660 }
16661 
duk_get_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16662 DUK_EXTERNAL duk_bool_t duk_get_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16663 	DUK_ASSERT_API_ENTRY(thr);
16664 
16665 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16666 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16667 	return duk_get_prop(thr, obj_idx);
16668 }
16669 
duk_get_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16670 DUK_INTERNAL duk_bool_t duk_get_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16671 	DUK_ASSERT_API_ENTRY(thr);
16672 	DUK_ASSERT_STRIDX_VALID(stridx);
16673 
16674 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16675 	(void) duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16676 	return duk_get_prop(thr, obj_idx);
16677 }
16678 
duk_get_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16679 DUK_INTERNAL duk_bool_t duk_get_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16680 	return duk_get_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16681 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16682 }
16683 
duk_get_prop_stridx_boolean(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_bool_t * out_has_prop)16684 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) {
16685 	duk_bool_t rc;
16686 
16687 	DUK_ASSERT_API_ENTRY(thr);
16688 	DUK_ASSERT_STRIDX_VALID(stridx);
16689 
16690 	rc = duk_get_prop_stridx(thr, obj_idx, stridx);
16691 	if (out_has_prop) {
16692 		*out_has_prop = rc;
16693 	}
16694 	return duk_to_boolean_top_pop(thr);
16695 }
16696 
duk__put_prop_shared(duk_hthread * thr,duk_idx_t obj_idx,duk_idx_t idx_key)16697 DUK_LOCAL duk_bool_t duk__put_prop_shared(duk_hthread *thr, duk_idx_t obj_idx, duk_idx_t idx_key) {
16698 	duk_tval *tv_obj;
16699 	duk_tval *tv_key;
16700 	duk_tval *tv_val;
16701 	duk_bool_t throw_flag;
16702 	duk_bool_t rc;
16703 
16704 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16705 	 * resize is not necessary for a property put right now (putprop protects
16706 	 * against it internally).
16707 	 */
16708 
16709 	/* Key and value indices are either (-2, -1) or (-1, -2).  Given idx_key,
16710 	 * idx_val is always (idx_key ^ 0x01).
16711 	 */
16712 	DUK_ASSERT((idx_key == -2 && (idx_key ^ 1) == -1) ||
16713 	           (idx_key == -1 && (idx_key ^ 1) == -2));
16714 	/* XXX: Direct access; faster validation. */
16715 	tv_obj = duk_require_tval(thr, obj_idx);
16716 	tv_key = duk_require_tval(thr, idx_key);
16717 	tv_val = duk_require_tval(thr, idx_key ^ 1);
16718 	throw_flag = duk_is_strict_call(thr);
16719 
16720 	rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, throw_flag);
16721 	DUK_ASSERT(rc == 0 || rc == 1);
16722 
16723 	duk_pop_2(thr);  /* remove key and value */
16724 	return rc;  /* 1 if property found, 0 otherwise */
16725 }
16726 
duk_put_prop(duk_hthread * thr,duk_idx_t obj_idx)16727 DUK_EXTERNAL duk_bool_t duk_put_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16728 	DUK_ASSERT_API_ENTRY(thr);
16729 	return duk__put_prop_shared(thr, obj_idx, -2);
16730 }
16731 
duk_put_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16732 DUK_EXTERNAL duk_bool_t duk_put_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16733 	DUK_ASSERT_API_ENTRY(thr);
16734 	DUK_ASSERT(key != NULL);
16735 
16736 	/* Careful here and with other duk_put_prop_xxx() helpers: the
16737 	 * target object and the property value may be in the same value
16738 	 * stack slot (unusual, but still conceptually clear).
16739 	 */
16740 	obj_idx = duk_normalize_index(thr, obj_idx);
16741 	(void) duk_push_string(thr, key);
16742 	return duk__put_prop_shared(thr, obj_idx, -1);
16743 }
16744 
duk_put_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16745 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) {
16746 	DUK_ASSERT_API_ENTRY(thr);
16747 	DUK_ASSERT(key != NULL);
16748 
16749 	obj_idx = duk_normalize_index(thr, obj_idx);
16750 	(void) duk_push_lstring(thr, key, key_len);
16751 	return duk__put_prop_shared(thr, obj_idx, -1);
16752 }
16753 
16754 #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)16755 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) {
16756 	DUK_ASSERT_API_ENTRY(thr);
16757 	DUK_ASSERT(key != NULL);
16758 	DUK_ASSERT(key[key_len] == (char) 0);
16759 
16760 	obj_idx = duk_normalize_index(thr, obj_idx);
16761 	(void) duk_push_literal_raw(thr, key, key_len);
16762 	return duk__put_prop_shared(thr, obj_idx, -1);
16763 }
16764 #endif
16765 
duk_put_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16766 DUK_EXTERNAL duk_bool_t duk_put_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16767 	DUK_ASSERT_API_ENTRY(thr);
16768 
16769 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16770 	duk_push_uarridx(thr, arr_idx);
16771 	return duk__put_prop_shared(thr, obj_idx, -1);
16772 }
16773 
duk_put_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16774 DUK_EXTERNAL duk_bool_t duk_put_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16775 	DUK_ASSERT_API_ENTRY(thr);
16776 
16777 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16778 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16779 	return duk__put_prop_shared(thr, obj_idx, -1);
16780 }
16781 
16782 
duk_put_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16783 DUK_INTERNAL duk_bool_t duk_put_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16784 	DUK_ASSERT_API_ENTRY(thr);
16785 	DUK_ASSERT_STRIDX_VALID(stridx);
16786 
16787 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16788 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16789 	return duk__put_prop_shared(thr, obj_idx, -1);
16790 }
16791 
duk_put_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)16792 DUK_INTERNAL duk_bool_t duk_put_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16793 	return duk_put_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16794 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16795 }
16796 
duk_del_prop(duk_hthread * thr,duk_idx_t obj_idx)16797 DUK_EXTERNAL duk_bool_t duk_del_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16798 	duk_tval *tv_obj;
16799 	duk_tval *tv_key;
16800 	duk_bool_t throw_flag;
16801 	duk_bool_t rc;
16802 
16803 	DUK_ASSERT_API_ENTRY(thr);
16804 
16805 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16806 	 * resize is not necessary for a property delete right now.
16807 	 */
16808 
16809 	tv_obj = duk_require_tval(thr, obj_idx);
16810 	tv_key = duk_require_tval(thr, -1);
16811 	throw_flag = duk_is_strict_call(thr);
16812 
16813 	rc = duk_hobject_delprop(thr, tv_obj, tv_key, throw_flag);
16814 	DUK_ASSERT(rc == 0 || rc == 1);
16815 
16816 	duk_pop(thr);  /* remove key */
16817 	return rc;
16818 }
16819 
duk_del_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16820 DUK_EXTERNAL duk_bool_t duk_del_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16821 	DUK_ASSERT_API_ENTRY(thr);
16822 	DUK_ASSERT(key != NULL);
16823 
16824 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16825 	(void) duk_push_string(thr, key);
16826 	return duk_del_prop(thr, obj_idx);
16827 }
16828 
duk_del_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16829 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) {
16830 	DUK_ASSERT_API_ENTRY(thr);
16831 	DUK_ASSERT(key != NULL);
16832 
16833 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16834 	(void) duk_push_lstring(thr, key, key_len);
16835 	return duk_del_prop(thr, obj_idx);
16836 }
16837 
16838 #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)16839 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) {
16840 	DUK_ASSERT_API_ENTRY(thr);
16841 	DUK_ASSERT(key != NULL);
16842 	DUK_ASSERT(key[key_len] == (char) 0);
16843 
16844 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16845 	(void) duk_push_literal_raw(thr, key, key_len);
16846 	return duk_del_prop(thr, obj_idx);
16847 }
16848 #endif
16849 
duk_del_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16850 DUK_EXTERNAL duk_bool_t duk_del_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16851 	DUK_ASSERT_API_ENTRY(thr);
16852 
16853 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16854 	duk_push_uarridx(thr, arr_idx);
16855 	return duk_del_prop(thr, obj_idx);
16856 }
16857 
duk_del_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16858 DUK_EXTERNAL duk_bool_t duk_del_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16859 	DUK_ASSERT_API_ENTRY(thr);
16860 
16861 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16862 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16863 	return duk_del_prop(thr, obj_idx);
16864 }
16865 
duk_del_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16866 DUK_INTERNAL duk_bool_t duk_del_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16867 	DUK_ASSERT_API_ENTRY(thr);
16868 	DUK_ASSERT_STRIDX_VALID(stridx);
16869 
16870 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16871 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16872 	return duk_del_prop(thr, obj_idx);
16873 }
16874 
16875 #if 0
16876 DUK_INTERNAL duk_bool_t duk_del_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16877 	return duk_del_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16878 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16879 }
16880 #endif
16881 
duk_has_prop(duk_hthread * thr,duk_idx_t obj_idx)16882 DUK_EXTERNAL duk_bool_t duk_has_prop(duk_hthread *thr, duk_idx_t obj_idx) {
16883 	duk_tval *tv_obj;
16884 	duk_tval *tv_key;
16885 	duk_bool_t rc;
16886 
16887 	DUK_ASSERT_API_ENTRY(thr);
16888 
16889 	/* Note: copying tv_obj and tv_key to locals to shield against a valstack
16890 	 * resize is not necessary for a property existence check right now.
16891 	 */
16892 
16893 	tv_obj = duk_require_tval(thr, obj_idx);
16894 	tv_key = duk_require_tval(thr, -1);
16895 
16896 	rc = duk_hobject_hasprop(thr, tv_obj, tv_key);
16897 	DUK_ASSERT(rc == 0 || rc == 1);
16898 
16899 	duk_pop(thr);  /* remove key */
16900 	return rc;  /* 1 if property found, 0 otherwise */
16901 }
16902 
duk_has_prop_string(duk_hthread * thr,duk_idx_t obj_idx,const char * key)16903 DUK_EXTERNAL duk_bool_t duk_has_prop_string(duk_hthread *thr, duk_idx_t obj_idx, const char *key) {
16904 	DUK_ASSERT_API_ENTRY(thr);
16905 	DUK_ASSERT(key != NULL);
16906 
16907 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16908 	(void) duk_push_string(thr, key);
16909 	return duk_has_prop(thr, obj_idx);
16910 }
16911 
duk_has_prop_lstring(duk_hthread * thr,duk_idx_t obj_idx,const char * key,duk_size_t key_len)16912 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) {
16913 	DUK_ASSERT_API_ENTRY(thr);
16914 	DUK_ASSERT(key != NULL);
16915 
16916 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16917 	(void) duk_push_lstring(thr, key, key_len);
16918 	return duk_has_prop(thr, obj_idx);
16919 }
16920 
16921 #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)16922 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) {
16923 	DUK_ASSERT_API_ENTRY(thr);
16924 	DUK_ASSERT(key != NULL);
16925 	DUK_ASSERT(key[key_len] == (char) 0);
16926 
16927 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16928 	(void) duk_push_literal_raw(thr, key, key_len);
16929 	return duk_has_prop(thr, obj_idx);
16930 }
16931 #endif
16932 
duk_has_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx)16933 DUK_EXTERNAL duk_bool_t duk_has_prop_index(duk_hthread *thr, duk_idx_t obj_idx, duk_uarridx_t arr_idx) {
16934 	DUK_ASSERT_API_ENTRY(thr);
16935 
16936 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16937 	duk_push_uarridx(thr, arr_idx);
16938 	return duk_has_prop(thr, obj_idx);
16939 }
16940 
duk_has_prop_heapptr(duk_hthread * thr,duk_idx_t obj_idx,void * ptr)16941 DUK_EXTERNAL duk_bool_t duk_has_prop_heapptr(duk_hthread *thr, duk_idx_t obj_idx, void *ptr) {
16942 	DUK_ASSERT_API_ENTRY(thr);
16943 
16944 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16945 	(void) duk_push_heapptr(thr, ptr);  /* NULL -> 'undefined' */
16946 	return duk_has_prop(thr, obj_idx);
16947 }
16948 
duk_has_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)16949 DUK_INTERNAL duk_bool_t duk_has_prop_stridx(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
16950 	DUK_ASSERT_API_ENTRY(thr);
16951 	DUK_ASSERT_STRIDX_VALID(stridx);
16952 
16953 	obj_idx = duk_require_normalize_index(thr, obj_idx);
16954 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
16955 	return duk_has_prop(thr, obj_idx);
16956 }
16957 
16958 #if 0
16959 DUK_INTERNAL duk_bool_t duk_has_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
16960 	return duk_has_prop_stridx(thr, (duk_idx_t) (duk_int16_t) (packed_args >> 16),
16961 	                                (duk_small_uint_t) (packed_args & 0xffffUL));
16962 }
16963 #endif
16964 
16965 /* Define own property without inheritance lookups and such.  This differs from
16966  * [[DefineOwnProperty]] because special behaviors (like Array 'length') are
16967  * not invoked by this method.  The caller must be careful to invoke any such
16968  * behaviors if necessary.
16969  */
duk_xdef_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t desc_flags)16970 DUK_INTERNAL void duk_xdef_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t desc_flags) {
16971 	duk_hobject *obj;
16972 	duk_hstring *key;
16973 
16974 	DUK_ASSERT_API_ENTRY(thr);
16975 
16976 	obj = duk_require_hobject(thr, obj_idx);
16977 	DUK_ASSERT(obj != NULL);
16978 	key = duk_to_property_key_hstring(thr, -2);
16979 	DUK_ASSERT(key != NULL);
16980 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
16981 
16982 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
16983 
16984 	duk_pop(thr);  /* pop key */
16985 }
16986 
duk_xdef_prop_index(duk_hthread * thr,duk_idx_t obj_idx,duk_uarridx_t arr_idx,duk_small_uint_t desc_flags)16987 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) {
16988 	duk_hobject *obj;
16989 
16990 	DUK_ASSERT_API_ENTRY(thr);
16991 
16992 	obj = duk_require_hobject(thr, obj_idx);
16993 	DUK_ASSERT(obj != NULL);
16994 
16995 	duk_hobject_define_property_internal_arridx(thr, obj, arr_idx, desc_flags);
16996 	/* value popped by call */
16997 }
16998 
duk_xdef_prop_stridx(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx,duk_small_uint_t desc_flags)16999 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) {
17000 	duk_hobject *obj;
17001 	duk_hstring *key;
17002 
17003 	DUK_ASSERT_API_ENTRY(thr);
17004 	DUK_ASSERT_STRIDX_VALID(stridx);
17005 
17006 	obj = duk_require_hobject(thr, obj_idx);
17007 	DUK_ASSERT(obj != NULL);
17008 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17009 	DUK_ASSERT(key != NULL);
17010 	DUK_ASSERT(duk_require_tval(thr, -1) != NULL);
17011 
17012 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17013 	/* value popped by call */
17014 }
17015 
duk_xdef_prop_stridx_short_raw(duk_hthread * thr,duk_uint_t packed_args)17016 DUK_INTERNAL void duk_xdef_prop_stridx_short_raw(duk_hthread *thr, duk_uint_t packed_args) {
17017 	duk_xdef_prop_stridx(thr, (duk_idx_t) (duk_int8_t) (packed_args >> 24),
17018 	                          (duk_small_uint_t) (packed_args >> 8) & 0xffffUL,
17019 	                          (duk_small_uint_t) (packed_args & 0xffL));
17020 }
17021 
17022 #if 0  /*unused*/
17023 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) {
17024 	duk_hobject *obj;
17025 	duk_hstring *key;
17026 
17027 	DUK_ASSERT_API_ENTRY(thr);
17028 	DUK_ASSERT_STRIDX_VALID(stridx);
17029 	DUK_ASSERT_BIDX_VALID(builtin_idx);
17030 
17031 	obj = duk_require_hobject(thr, obj_idx);
17032 	DUK_ASSERT(obj != NULL);
17033 	key = DUK_HTHREAD_GET_STRING(thr, stridx);
17034 	DUK_ASSERT(key != NULL);
17035 
17036 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
17037 	duk_hobject_define_property_internal(thr, obj, key, desc_flags);
17038 	/* value popped by call */
17039 }
17040 #endif
17041 
17042 /* This is a rare property helper; it sets the global thrower (E5 Section 13.2.3)
17043  * setter/getter into an object property.  This is needed by the 'arguments'
17044  * object creation code, function instance creation code, and Function.prototype.bind().
17045  */
17046 
duk_xdef_prop_stridx_thrower(duk_hthread * thr,duk_idx_t obj_idx,duk_small_uint_t stridx)17047 DUK_INTERNAL void duk_xdef_prop_stridx_thrower(duk_hthread *thr, duk_idx_t obj_idx, duk_small_uint_t stridx) {
17048 	DUK_ASSERT_API_ENTRY(thr);
17049 
17050 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17051 	duk_push_hstring_stridx(thr, stridx);
17052 	duk_push_hobject_bidx(thr, DUK_BIDX_TYPE_ERROR_THROWER);
17053 	duk_dup_top(thr);
17054 	duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_SETTER | DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_FORCE);  /* attributes always 0 */
17055 }
17056 
17057 /* Object.getOwnPropertyDescriptor() equivalent C binding. */
duk_get_prop_desc(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17058 DUK_EXTERNAL void duk_get_prop_desc(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17059 	DUK_ASSERT_API_ENTRY(thr);
17060 	DUK_UNREF(flags);  /* no flags defined yet */
17061 
17062 	duk_hobject_object_get_own_property_descriptor(thr, obj_idx);  /* [ ... key ] -> [ ... desc ] */
17063 }
17064 
17065 /* Object.defineProperty() equivalent C binding. */
duk_def_prop(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t flags)17066 DUK_EXTERNAL void duk_def_prop(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t flags) {
17067 	duk_idx_t idx_base;
17068 	duk_hobject *obj;
17069 	duk_hstring *key;
17070 	duk_idx_t idx_value;
17071 	duk_hobject *get;
17072 	duk_hobject *set;
17073 	duk_uint_t is_data_desc;
17074 	duk_uint_t is_acc_desc;
17075 
17076 	DUK_ASSERT_API_ENTRY(thr);
17077 
17078 	obj = duk_require_hobject(thr, obj_idx);
17079 
17080 	is_data_desc = flags & (DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
17081 	is_acc_desc = flags & (DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
17082 	if (is_data_desc && is_acc_desc) {
17083 		/* "Have" flags must not be conflicting so that they would
17084 		 * apply to both a plain property and an accessor at the same
17085 		 * time.
17086 		 */
17087 		goto fail_invalid_desc;
17088 	}
17089 
17090 	idx_base = duk_get_top_index(thr);
17091 	if (flags & DUK_DEFPROP_HAVE_SETTER) {
17092 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17093 		                                     DUK_TYPE_MASK_OBJECT |
17094 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17095 		set = duk_get_hobject_promote_lfunc(thr, idx_base);
17096 		if (set != NULL && !DUK_HOBJECT_IS_CALLABLE(set)) {
17097 			goto fail_not_callable;
17098 		}
17099 		idx_base--;
17100 	} else {
17101 		set = NULL;
17102 	}
17103 	if (flags & DUK_DEFPROP_HAVE_GETTER) {
17104 		duk_require_type_mask(thr, idx_base, DUK_TYPE_MASK_UNDEFINED |
17105 		                                     DUK_TYPE_MASK_OBJECT |
17106 		                                     DUK_TYPE_MASK_LIGHTFUNC);
17107 		get = duk_get_hobject_promote_lfunc(thr, idx_base);
17108 		if (get != NULL && !DUK_HOBJECT_IS_CALLABLE(get)) {
17109 			goto fail_not_callable;
17110 		}
17111 		idx_base--;
17112 	} else {
17113 		get = NULL;
17114 	}
17115 	if (flags & DUK_DEFPROP_HAVE_VALUE) {
17116 		idx_value = idx_base;
17117 		idx_base--;
17118 	} else {
17119 		idx_value = (duk_idx_t) -1;
17120 	}
17121 	key = duk_to_property_key_hstring(thr, idx_base);
17122 	DUK_ASSERT(key != NULL);
17123 
17124 	duk_require_valid_index(thr, idx_base);
17125 
17126 	duk_hobject_define_property_helper(thr,
17127 	                                   flags /*defprop_flags*/,
17128 	                                   obj,
17129 	                                   key,
17130 	                                   idx_value,
17131 	                                   get,
17132 	                                   set,
17133 	                                   1 /*throw_flag*/);
17134 
17135 	/* Clean up stack */
17136 
17137 	duk_set_top(thr, idx_base);
17138 
17139 	/* [ ... obj ... ] */
17140 
17141 	return;
17142 
17143  fail_invalid_desc:
17144 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
17145 	DUK_WO_NORETURN(return;);
17146 
17147  fail_not_callable:
17148 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17149 	DUK_WO_NORETURN(return;);
17150 }
17151 
17152 /*
17153  *  Object related
17154  *
17155  *  Note: seal() and freeze() are accessible through ECMAScript bindings,
17156  *  and are not exposed through the API.
17157  */
17158 
duk_compact(duk_hthread * thr,duk_idx_t obj_idx)17159 DUK_EXTERNAL void duk_compact(duk_hthread *thr, duk_idx_t obj_idx) {
17160 	duk_hobject *obj;
17161 
17162 	DUK_ASSERT_API_ENTRY(thr);
17163 
17164 	obj = duk_get_hobject(thr, obj_idx);
17165 	if (obj) {
17166 		/* Note: this may fail, caller should protect the call if necessary */
17167 		duk_hobject_compact_props(thr, obj);
17168 	}
17169 }
17170 
duk_compact_m1(duk_hthread * thr)17171 DUK_INTERNAL void duk_compact_m1(duk_hthread *thr) {
17172 	DUK_ASSERT_API_ENTRY(thr);
17173 
17174 	duk_compact(thr, -1);
17175 }
17176 
17177 /* XXX: the duk_hobject_enum.c stack APIs should be reworked */
17178 
duk_enum(duk_hthread * thr,duk_idx_t obj_idx,duk_uint_t enum_flags)17179 DUK_EXTERNAL void duk_enum(duk_hthread *thr, duk_idx_t obj_idx, duk_uint_t enum_flags) {
17180 	DUK_ASSERT_API_ENTRY(thr);
17181 
17182 	duk_dup(thr, obj_idx);
17183 	duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
17184 	duk_hobject_enumerator_create(thr, enum_flags);   /* [target] -> [enum] */
17185 }
17186 
duk_next(duk_hthread * thr,duk_idx_t enum_index,duk_bool_t get_value)17187 DUK_EXTERNAL duk_bool_t duk_next(duk_hthread *thr, duk_idx_t enum_index, duk_bool_t get_value) {
17188 	DUK_ASSERT_API_ENTRY(thr);
17189 
17190 	duk_require_hobject(thr, enum_index);
17191 	duk_dup(thr, enum_index);
17192 	return duk_hobject_enumerator_next(thr, get_value);
17193 }
17194 
duk_seal_freeze_raw(duk_hthread * thr,duk_idx_t obj_idx,duk_bool_t is_freeze)17195 DUK_INTERNAL void duk_seal_freeze_raw(duk_hthread *thr, duk_idx_t obj_idx, duk_bool_t is_freeze) {
17196 	duk_tval *tv;
17197 	duk_hobject *h;
17198 
17199 	DUK_ASSERT_API_ENTRY(thr);
17200 
17201 	tv = duk_require_tval(thr, obj_idx);
17202 	DUK_ASSERT(tv != NULL);
17203 
17204 	/* Seal/freeze are quite rare in practice so it'd be nice to get the
17205 	 * correct behavior simply via automatic promotion (at the cost of some
17206 	 * memory churn).  However, the promoted objects don't behave the same,
17207 	 * e.g. promoted lightfuncs are extensible.
17208 	 */
17209 
17210 	switch (DUK_TVAL_GET_TAG(tv)) {
17211 	case DUK_TAG_BUFFER:
17212 		/* Plain buffer: already sealed, but not frozen (and can't be frozen
17213 		 * because index properties can't be made non-writable.
17214 		 */
17215 		if (is_freeze) {
17216 			goto fail_cannot_freeze;
17217 		}
17218 		break;
17219 	case DUK_TAG_LIGHTFUNC:
17220 		/* Lightfunc: already sealed and frozen, success. */
17221 		break;
17222 	case DUK_TAG_OBJECT:
17223 		h = DUK_TVAL_GET_OBJECT(tv);
17224 		DUK_ASSERT(h != NULL);
17225 		if (is_freeze && DUK_HOBJECT_IS_BUFOBJ(h)) {
17226 			/* Buffer objects cannot be frozen because there's no internal
17227 			 * support for making virtual array indices non-writable.
17228 			 */
17229 			DUK_DD(DUK_DDPRINT("cannot freeze a buffer object"));
17230 			goto fail_cannot_freeze;
17231 		}
17232 		duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
17233 
17234 		/* Sealed and frozen objects cannot gain any more properties,
17235 		 * so this is a good time to compact them.
17236 		 */
17237 		duk_hobject_compact_props(thr, h);
17238 		break;
17239 	default:
17240 		/* ES2015 Sections 19.1.2.5, 19.1.2.17 */
17241 		break;
17242 	}
17243 	return;
17244 
17245  fail_cannot_freeze:
17246 	DUK_ERROR_TYPE_INVALID_ARGS(thr);  /* XXX: proper error message */
17247 	DUK_WO_NORETURN(return;);
17248 }
17249 
duk_seal(duk_hthread * thr,duk_idx_t obj_idx)17250 DUK_EXTERNAL void duk_seal(duk_hthread *thr, duk_idx_t obj_idx) {
17251 	DUK_ASSERT_API_ENTRY(thr);
17252 
17253 	duk_seal_freeze_raw(thr, obj_idx, 0 /*is_freeze*/);
17254 }
17255 
duk_freeze(duk_hthread * thr,duk_idx_t obj_idx)17256 DUK_EXTERNAL void duk_freeze(duk_hthread *thr, duk_idx_t obj_idx) {
17257 	DUK_ASSERT_API_ENTRY(thr);
17258 
17259 	duk_seal_freeze_raw(thr, obj_idx, 1 /*is_freeze*/);
17260 }
17261 
17262 /*
17263  *  Helpers for writing multiple properties
17264  */
17265 
duk_put_function_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_function_list_entry * funcs)17266 DUK_EXTERNAL void duk_put_function_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_function_list_entry *funcs) {
17267 	const duk_function_list_entry *ent = funcs;
17268 
17269 	DUK_ASSERT_API_ENTRY(thr);
17270 
17271 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17272 	if (ent != NULL) {
17273 		while (ent->key != NULL) {
17274 			duk_push_c_function(thr, ent->value, ent->nargs);
17275 			duk_put_prop_string(thr, obj_idx, ent->key);
17276 			ent++;
17277 		}
17278 	}
17279 }
17280 
duk_put_number_list(duk_hthread * thr,duk_idx_t obj_idx,const duk_number_list_entry * numbers)17281 DUK_EXTERNAL void duk_put_number_list(duk_hthread *thr, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
17282 	const duk_number_list_entry *ent = numbers;
17283 	duk_tval *tv;
17284 
17285 	DUK_ASSERT_API_ENTRY(thr);
17286 
17287 	obj_idx = duk_require_normalize_index(thr, obj_idx);
17288 	if (ent != NULL) {
17289 		while (ent->key != NULL) {
17290 			tv = thr->valstack_top++;
17291 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));  /* value stack init policy */
17292 			DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value);  /* no need for decref/incref */
17293 			duk_put_prop_string(thr, obj_idx, ent->key);
17294 			ent++;
17295 		}
17296 	}
17297 }
17298 
17299 /*
17300  *  Shortcut for accessing global object properties
17301  */
17302 
duk_get_global_string(duk_hthread * thr,const char * key)17303 DUK_EXTERNAL duk_bool_t duk_get_global_string(duk_hthread *thr, const char *key) {
17304 	duk_bool_t ret;
17305 
17306 	DUK_ASSERT_API_ENTRY(thr);
17307 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17308 
17309 	/* XXX: direct implementation */
17310 
17311 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17312 	ret = duk_get_prop_string(thr, -1, key);
17313 	duk_remove_m2(thr);
17314 	return ret;
17315 }
17316 
duk_get_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17317 DUK_EXTERNAL duk_bool_t duk_get_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17318 	duk_bool_t ret;
17319 
17320 	DUK_ASSERT_API_ENTRY(thr);
17321 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17322 
17323 	/* XXX: direct implementation */
17324 
17325 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17326 	ret = duk_get_prop_lstring(thr, -1, key, key_len);
17327 	duk_remove_m2(thr);
17328 	return ret;
17329 }
17330 
17331 #if !defined(DUK_USE_PREFER_SIZE)
duk_get_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17332 DUK_EXTERNAL duk_bool_t duk_get_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17333 	duk_bool_t ret;
17334 
17335 	DUK_ASSERT_API_ENTRY(thr);
17336 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17337 	DUK_ASSERT(key[key_len] == (char) 0);
17338 
17339 	/* XXX: direct implementation */
17340 
17341 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17342 	ret = duk_get_prop_literal_raw(thr, -1, key, key_len);
17343 	duk_remove_m2(thr);
17344 	return ret;
17345 }
17346 #endif
17347 
duk_get_global_heapptr(duk_hthread * thr,void * ptr)17348 DUK_EXTERNAL duk_bool_t duk_get_global_heapptr(duk_hthread *thr, void *ptr) {
17349 	duk_bool_t ret;
17350 
17351 	DUK_ASSERT_API_ENTRY(thr);
17352 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17353 
17354 	/* XXX: direct implementation */
17355 
17356 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17357 	ret = duk_get_prop_heapptr(thr, -1, ptr);
17358 	duk_remove_m2(thr);
17359 	return ret;
17360 }
17361 
17362 
duk_put_global_string(duk_hthread * thr,const char * key)17363 DUK_EXTERNAL duk_bool_t duk_put_global_string(duk_hthread *thr, const char *key) {
17364 	duk_bool_t ret;
17365 
17366 	DUK_ASSERT_API_ENTRY(thr);
17367 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17368 
17369 	/* XXX: direct implementation */
17370 
17371 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17372 	duk_insert(thr, -2);
17373 	ret = duk_put_prop_string(thr, -2, key);  /* [ ... global val ] -> [ ... global ] */
17374 	duk_pop(thr);
17375 	return ret;
17376 }
17377 
duk_put_global_lstring(duk_hthread * thr,const char * key,duk_size_t key_len)17378 DUK_EXTERNAL duk_bool_t duk_put_global_lstring(duk_hthread *thr, const char *key, duk_size_t key_len) {
17379 	duk_bool_t ret;
17380 
17381 	DUK_ASSERT_API_ENTRY(thr);
17382 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17383 
17384 	/* XXX: direct implementation */
17385 
17386 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17387 	duk_insert(thr, -2);
17388 	ret = duk_put_prop_lstring(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17389 	duk_pop(thr);
17390 	return ret;
17391 }
17392 
17393 #if !defined(DUK_USE_PREFER_SIZE)
duk_put_global_literal_raw(duk_hthread * thr,const char * key,duk_size_t key_len)17394 DUK_EXTERNAL duk_bool_t duk_put_global_literal_raw(duk_hthread *thr, const char *key, duk_size_t key_len) {
17395 	duk_bool_t ret;
17396 
17397 	DUK_ASSERT_API_ENTRY(thr);
17398 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17399 	DUK_ASSERT(key[key_len] == (char) 0);
17400 
17401 	/* XXX: direct implementation */
17402 
17403 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17404 	duk_insert(thr, -2);
17405 	ret = duk_put_prop_literal_raw(thr, -2, key, key_len);  /* [ ... global val ] -> [ ... global ] */
17406 	duk_pop(thr);
17407 	return ret;
17408 }
17409 #endif
17410 
duk_put_global_heapptr(duk_hthread * thr,void * ptr)17411 DUK_EXTERNAL duk_bool_t duk_put_global_heapptr(duk_hthread *thr, void *ptr) {
17412 	duk_bool_t ret;
17413 
17414 	DUK_ASSERT_API_ENTRY(thr);
17415 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
17416 
17417 	/* XXX: direct implementation */
17418 
17419 	duk_push_hobject(thr, thr->builtins[DUK_BIDX_GLOBAL]);
17420 	duk_insert(thr, -2);
17421 	ret = duk_put_prop_heapptr(thr, -2, ptr);  /* [ ... global val ] -> [ ... global ] */
17422 	duk_pop(thr);
17423 	return ret;
17424 }
17425 
17426 /*
17427  *  ES2015 GetMethod()
17428  */
17429 
duk_get_method_stridx(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t stridx)17430 DUK_INTERNAL duk_bool_t duk_get_method_stridx(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t stridx) {
17431 	(void) duk_get_prop_stridx(thr, idx, stridx);
17432 	if (duk_is_null_or_undefined(thr, -1)) {
17433 		duk_pop_nodecref_unsafe(thr);
17434 		return 0;
17435 	}
17436 	if (!duk_is_callable(thr, -1)) {
17437 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
17438 		DUK_WO_NORETURN(return 0;);
17439 	}
17440 	return 1;
17441 }
17442 
17443 /*
17444  *  Object prototype
17445  */
17446 
duk_get_prototype(duk_hthread * thr,duk_idx_t idx)17447 DUK_EXTERNAL void duk_get_prototype(duk_hthread *thr, duk_idx_t idx) {
17448 	duk_hobject *obj;
17449 	duk_hobject *proto;
17450 
17451 	DUK_ASSERT_API_ENTRY(thr);
17452 
17453 	obj = duk_require_hobject(thr, idx);
17454 	DUK_ASSERT(obj != NULL);
17455 
17456 	/* XXX: shared helper for duk_push_hobject_or_undefined()? */
17457 	proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, obj);
17458 	if (proto) {
17459 		duk_push_hobject(thr, proto);
17460 	} else {
17461 		duk_push_undefined(thr);
17462 	}
17463 }
17464 
duk_set_prototype(duk_hthread * thr,duk_idx_t idx)17465 DUK_EXTERNAL void duk_set_prototype(duk_hthread *thr, duk_idx_t idx) {
17466 	duk_hobject *obj;
17467 	duk_hobject *proto;
17468 
17469 	DUK_ASSERT_API_ENTRY(thr);
17470 
17471 	obj = duk_require_hobject(thr, idx);
17472 	DUK_ASSERT(obj != NULL);
17473 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_UNDEFINED |
17474 	                               DUK_TYPE_MASK_OBJECT);
17475 	proto = duk_get_hobject(thr, -1);
17476 	/* proto can also be NULL here (allowed explicitly) */
17477 
17478 #if defined(DUK_USE_ROM_OBJECTS)
17479 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
17480 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);  /* XXX: "read only object"? */
17481 		DUK_WO_NORETURN(return;);
17482 	}
17483 #endif
17484 
17485 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, obj, proto);
17486 
17487 	duk_pop(thr);
17488 }
17489 
17490 /*
17491  *  Object finalizer
17492  */
17493 
17494 #if defined(DUK_USE_FINALIZER_SUPPORT)
17495 /* XXX: these could be implemented as macros calling an internal function
17496  * directly.
17497  * XXX: same issue as with Duktape.fin: there's no way to delete the property
17498  * now (just set it to undefined).
17499  */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17500 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17501 	DUK_ASSERT_API_ENTRY(thr);
17502 
17503 	duk_get_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17504 }
17505 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17506 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17507 	duk_hobject *h;
17508 	duk_bool_t callable;
17509 
17510 	DUK_ASSERT_API_ENTRY(thr);
17511 
17512 	h = duk_require_hobject(thr, idx);  /* Get before 'put' so that 'idx' is correct. */
17513 	callable = duk_is_callable(thr, -1);
17514 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_INT_FINALIZER);
17515 
17516 	/* In addition to setting the finalizer property, keep a "have
17517 	 * finalizer" flag in duk_hobject in sync so that refzero can do
17518 	 * a very quick finalizer check by walking the prototype chain
17519 	 * and checking the flag alone.  (Note that this means that just
17520 	 * setting _Finalizer on an object won't affect finalizer checks.)
17521 	 *
17522 	 * NOTE: if the argument is a Proxy object, this flag will be set
17523 	 * on the Proxy, not the target.  As a result, the target won't get
17524 	 * a finalizer flag and the Proxy also won't be finalized as there's
17525 	 * an explicit Proxy check in finalization now.
17526 	 */
17527 	if (callable) {
17528 		DUK_HOBJECT_SET_HAVE_FINALIZER(h);
17529 	} else {
17530 		DUK_HOBJECT_CLEAR_HAVE_FINALIZER(h);
17531 	}
17532 }
17533 #else  /* DUK_USE_FINALIZER_SUPPORT */
duk_get_finalizer(duk_hthread * thr,duk_idx_t idx)17534 DUK_EXTERNAL void duk_get_finalizer(duk_hthread *thr, duk_idx_t idx) {
17535 	DUK_ASSERT_API_ENTRY(thr);
17536 	DUK_UNREF(idx);
17537 	DUK_ERROR_UNSUPPORTED(thr);
17538 	DUK_WO_NORETURN(return;);
17539 }
17540 
duk_set_finalizer(duk_hthread * thr,duk_idx_t idx)17541 DUK_EXTERNAL void duk_set_finalizer(duk_hthread *thr, duk_idx_t idx) {
17542 	DUK_ASSERT_API_ENTRY(thr);
17543 	DUK_UNREF(idx);
17544 	DUK_ERROR_UNSUPPORTED(thr);
17545 	DUK_WO_NORETURN(return;);
17546 }
17547 #endif  /* DUK_USE_FINALIZER_SUPPORT */
17548 #line 1 "duk_api_random.c"
17549 /*
17550  *  Random numbers
17551  */
17552 
17553 /* #include duk_internal.h -> already included */
17554 
duk_random(duk_hthread * thr)17555 DUK_EXTERNAL duk_double_t duk_random(duk_hthread *thr) {
17556 	return (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr);
17557 }
17558 #line 1 "duk_api_stack.c"
17559 /*
17560  *  API calls related to general value stack manipulation: resizing the value
17561  *  stack, pushing and popping values, type checking and reading values,
17562  *  coercing values, etc.
17563  *
17564  *  Also contains internal functions (such as duk_get_tval()), defined
17565  *  in duk_api_internal.h, with semantics similar to the public API.
17566  */
17567 
17568 /* XXX: repetition of stack pre-checks -> helper or macro or inline */
17569 /* XXX: shared api error strings, and perhaps even throw code for rare cases? */
17570 
17571 /* #include duk_internal.h -> already included */
17572 
17573 /*
17574  *  Forward declarations
17575  */
17576 
17577 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);
17578 
17579 /*
17580  *  Global state for working around missing variadic macros
17581  */
17582 
17583 #if !defined(DUK_USE_VARIADIC_MACROS)
17584 DUK_EXTERNAL const char *duk_api_global_filename = NULL;
17585 DUK_EXTERNAL duk_int_t duk_api_global_line = 0;
17586 #endif
17587 
17588 /*
17589  *  Misc helpers
17590  */
17591 
17592 DUK_LOCAL const char * const duk__symbol_type_strings[4] = {
17593 	"hidden", "global", "local", "wellknown"
17594 };
17595 
17596 #if !defined(DUK_USE_PACKED_TVAL)
17597 DUK_LOCAL const duk_uint_t duk__type_from_tag[] = {
17598 	DUK_TYPE_NUMBER,
17599 	DUK_TYPE_NUMBER,  /* fastint */
17600 	DUK_TYPE_UNDEFINED,
17601 	DUK_TYPE_NULL,
17602 	DUK_TYPE_BOOLEAN,
17603 	DUK_TYPE_POINTER,
17604 	DUK_TYPE_LIGHTFUNC,
17605 	DUK_TYPE_NONE,
17606 	DUK_TYPE_STRING,
17607 	DUK_TYPE_OBJECT,
17608 	DUK_TYPE_BUFFER,
17609 };
17610 DUK_LOCAL const duk_uint_t duk__type_mask_from_tag[] = {
17611 	DUK_TYPE_MASK_NUMBER,
17612 	DUK_TYPE_MASK_NUMBER,  /* fastint */
17613 	DUK_TYPE_MASK_UNDEFINED,
17614 	DUK_TYPE_MASK_NULL,
17615 	DUK_TYPE_MASK_BOOLEAN,
17616 	DUK_TYPE_MASK_POINTER,
17617 	DUK_TYPE_MASK_LIGHTFUNC,
17618 	DUK_TYPE_MASK_NONE,
17619 	DUK_TYPE_MASK_STRING,
17620 	DUK_TYPE_MASK_OBJECT,
17621 	DUK_TYPE_MASK_BUFFER,
17622 };
17623 #endif  /* !DUK_USE_PACKED_TVAL */
17624 
17625 /* Assert that there's room for one value. */
17626 #define DUK__ASSERT_SPACE() do { \
17627 		DUK_ASSERT(!(thr->valstack_top >= thr->valstack_end)); \
17628 	} while (0)
17629 
17630 /* Check that there's room to push one value. */
17631 #if defined(DUK_USE_VALSTACK_UNSAFE)
17632 /* Faster but value stack overruns are memory unsafe. */
17633 #define DUK__CHECK_SPACE() DUK__ASSERT_SPACE()
17634 #else
17635 #define DUK__CHECK_SPACE() do { \
17636 		if (DUK_UNLIKELY(thr->valstack_top >= thr->valstack_end)) { \
17637 			DUK_ERROR_RANGE_PUSH_BEYOND(thr); \
17638 		} \
17639 	} while (0)
17640 #endif
17641 
duk__get_symbol_type(duk_hstring * h)17642 DUK_LOCAL duk_small_uint_t duk__get_symbol_type(duk_hstring *h) {
17643 	const duk_uint8_t *data;
17644 	duk_size_t len;
17645 
17646 	DUK_ASSERT(h != NULL);
17647 	DUK_ASSERT(DUK_HSTRING_HAS_SYMBOL(h));
17648 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(h) >= 1);  /* always true, symbol prefix */
17649 
17650 	data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
17651 	len = DUK_HSTRING_GET_BYTELEN(h);
17652 	DUK_ASSERT(len >= 1);
17653 
17654 	/* XXX: differentiate between 0x82 and 0xff (hidden vs. internal?)? */
17655 
17656 	if (data[0] == 0xffU) {
17657 		return DUK_SYMBOL_TYPE_HIDDEN;
17658 	} else if (data[0] == 0x82U) {
17659 		return DUK_SYMBOL_TYPE_HIDDEN;
17660 	} else if (data[0] == 0x80U) {
17661 		return DUK_SYMBOL_TYPE_GLOBAL;
17662 	} else if (data[len - 1] != 0xffU) {
17663 		return DUK_SYMBOL_TYPE_LOCAL;
17664 	} else {
17665 		return DUK_SYMBOL_TYPE_WELLKNOWN;
17666 	}
17667 }
17668 
duk__get_symbol_type_string(duk_hstring * h)17669 DUK_LOCAL const char *duk__get_symbol_type_string(duk_hstring *h) {
17670 	duk_small_uint_t idx;
17671 	idx = duk__get_symbol_type(h);
17672 	DUK_ASSERT(idx < sizeof(duk__symbol_type_strings));
17673 	return duk__symbol_type_strings[idx];
17674 }
17675 
17676 DUK_LOCAL_DECL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag);
17677 
duk__api_coerce_d2i(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value,duk_bool_t require)17678 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) {
17679 	duk_tval *tv;
17680 	duk_small_int_t c;
17681 	duk_double_t d;
17682 
17683 	tv = duk_get_tval_or_unused(thr, idx);
17684 	DUK_ASSERT(tv != NULL);
17685 
17686 	/*
17687 	 *  Special cases like NaN and +/- Infinity are handled explicitly
17688 	 *  because a plain C coercion from double to int handles these cases
17689 	 *  in undesirable ways.  For instance, NaN may coerce to INT_MIN
17690 	 *  (not zero), and INT_MAX + 1 may coerce to INT_MIN (not INT_MAX).
17691 	 *
17692 	 *  This double-to-int coercion differs from ToInteger() because it
17693 	 *  has a finite range (ToInteger() allows e.g. +/- Infinity).  It
17694 	 *  also differs from ToInt32() because the INT_MIN/INT_MAX clamping
17695 	 *  depends on the size of the int type on the platform.  In particular,
17696 	 *  on platforms with a 64-bit int type, the full range is allowed.
17697 	 */
17698 
17699 #if defined(DUK_USE_FASTINT)
17700 	if (DUK_TVAL_IS_FASTINT(tv)) {
17701 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17702 #if (DUK_INT_MAX <= 0x7fffffffL)
17703 		/* Clamping only necessary for 32-bit ints. */
17704 		if (t < DUK_INT_MIN) {
17705 			t = DUK_INT_MIN;
17706 		} else if (t > DUK_INT_MAX) {
17707 			t = DUK_INT_MAX;
17708 		}
17709 #endif
17710 		return (duk_int_t) t;
17711 	}
17712 #endif
17713 
17714 	if (DUK_TVAL_IS_NUMBER(tv)) {
17715 		d = DUK_TVAL_GET_NUMBER(tv);
17716 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17717 		if (c == DUK_FP_NAN) {
17718 			return 0;
17719 		} else if (d < (duk_double_t) DUK_INT_MIN) {
17720 			/* covers -Infinity */
17721 			return DUK_INT_MIN;
17722 		} else if (d > (duk_double_t) DUK_INT_MAX) {
17723 			/* covers +Infinity */
17724 			return DUK_INT_MAX;
17725 		} else {
17726 			/* coerce towards zero */
17727 			return (duk_int_t) d;
17728 		}
17729 	}
17730 
17731 	if (require) {
17732 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17733 		DUK_WO_NORETURN(return 0;);
17734 	}
17735 
17736 	return def_value;
17737 }
17738 
duk__api_coerce_d2ui(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value,duk_bool_t require)17739 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) {
17740 	duk_tval *tv;
17741 	duk_small_int_t c;
17742 	duk_double_t d;
17743 
17744 	/* Same as above but for unsigned int range. */
17745 
17746 	tv = duk_get_tval_or_unused(thr, idx);
17747 	DUK_ASSERT(tv != NULL);
17748 
17749 #if defined(DUK_USE_FASTINT)
17750 	if (DUK_TVAL_IS_FASTINT(tv)) {
17751 		duk_int64_t t = DUK_TVAL_GET_FASTINT(tv);
17752 		if (t < 0) {
17753 			t = 0;
17754 		}
17755 #if (DUK_UINT_MAX <= 0xffffffffUL)
17756 		/* Clamping only necessary for 32-bit ints. */
17757 		else if (t > DUK_UINT_MAX) {
17758 			t = DUK_UINT_MAX;
17759 		}
17760 #endif
17761 		return (duk_uint_t) t;
17762 	}
17763 #endif
17764 
17765 	if (DUK_TVAL_IS_NUMBER(tv)) {
17766 		d = DUK_TVAL_GET_NUMBER(tv);
17767 		c = (duk_small_int_t) DUK_FPCLASSIFY(d);
17768 		if (c == DUK_FP_NAN) {
17769 			return 0;
17770 		} else if (d < 0.0) {
17771 			/* covers -Infinity */
17772 			return (duk_uint_t) 0;
17773 		} else if (d > (duk_double_t) DUK_UINT_MAX) {
17774 			/* covers +Infinity */
17775 			return (duk_uint_t) DUK_UINT_MAX;
17776 		} else {
17777 			/* coerce towards zero */
17778 			return (duk_uint_t) d;
17779 		}
17780 	}
17781 
17782 	if (require) {
17783 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
17784 		DUK_WO_NORETURN(return 0;);
17785 	}
17786 
17787 	return def_value;
17788 }
17789 
17790 /*
17791  *  Stack index validation/normalization and getting a stack duk_tval ptr.
17792  *
17793  *  These are called by many API entrypoints so the implementations must be
17794  *  fast and "inlined".
17795  *
17796  *  There's some repetition because of this; keep the functions in sync.
17797  */
17798 
duk_normalize_index(duk_hthread * thr,duk_idx_t idx)17799 DUK_EXTERNAL duk_idx_t duk_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17800 	duk_uidx_t vs_size;
17801 	duk_uidx_t uidx;
17802 
17803 	DUK_ASSERT_API_ENTRY(thr);
17804 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17805 
17806 	/* Care must be taken to avoid pointer wrapping in the index
17807 	 * validation.  For instance, on a 32-bit platform with 8-byte
17808 	 * duk_tval the index 0x20000000UL would wrap the memory space
17809 	 * once.
17810 	 */
17811 
17812 	/* Assume value stack sizes (in elements) fits into duk_idx_t. */
17813 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17814 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17815 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17816 
17817 	if (idx < 0) {
17818 		uidx = vs_size + (duk_uidx_t) idx;
17819 	} else {
17820 		/* since index non-negative */
17821 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17822 		uidx = (duk_uidx_t) idx;
17823 	}
17824 
17825 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17826 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17827 
17828 	if (DUK_LIKELY(uidx < vs_size)) {
17829 		return (duk_idx_t) uidx;
17830 	}
17831 	return DUK_INVALID_INDEX;
17832 }
17833 
duk_require_normalize_index(duk_hthread * thr,duk_idx_t idx)17834 DUK_EXTERNAL duk_idx_t duk_require_normalize_index(duk_hthread *thr, duk_idx_t idx) {
17835 	duk_uidx_t vs_size;
17836 	duk_uidx_t uidx;
17837 
17838 	DUK_ASSERT_API_ENTRY(thr);
17839 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17840 
17841 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17842 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17843 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17844 
17845 	if (idx < 0) {
17846 		uidx = vs_size + (duk_uidx_t) idx;
17847 	} else {
17848 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17849 		uidx = (duk_uidx_t) idx;
17850 	}
17851 
17852 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17853 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17854 
17855 	if (DUK_LIKELY(uidx < vs_size)) {
17856 		return (duk_idx_t) uidx;
17857 	}
17858 	DUK_ERROR_RANGE_INDEX(thr, idx);
17859 	DUK_WO_NORETURN(return 0;);
17860 }
17861 
duk_get_tval(duk_hthread * thr,duk_idx_t idx)17862 DUK_INTERNAL duk_tval *duk_get_tval(duk_hthread *thr, duk_idx_t idx) {
17863 	duk_uidx_t vs_size;
17864 	duk_uidx_t uidx;
17865 
17866 	DUK_ASSERT_API_ENTRY(thr);
17867 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17868 
17869 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17870 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17871 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17872 
17873 	if (idx < 0) {
17874 		uidx = vs_size + (duk_uidx_t) idx;
17875 	} else {
17876 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17877 		uidx = (duk_uidx_t) idx;
17878 	}
17879 
17880 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17881 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17882 
17883 	if (DUK_LIKELY(uidx < vs_size)) {
17884 		return thr->valstack_bottom + uidx;
17885 	}
17886 	return NULL;
17887 }
17888 
17889 /* Variant of duk_get_tval() which is guaranteed to return a valid duk_tval
17890  * pointer.  When duk_get_tval() would return NULL, this variant returns a
17891  * pointer to a duk_tval with tag DUK_TAG_UNUSED.  This allows the call site
17892  * to avoid an unnecessary NULL check which sometimes leads to better code.
17893  * The return duk_tval is read only (at least for the UNUSED value).
17894  */
17895 DUK_LOCAL const duk_tval_unused duk__const_tval_unused = DUK_TVAL_UNUSED_INITIALIZER();
17896 
duk_get_tval_or_unused(duk_hthread * thr,duk_idx_t idx)17897 DUK_INTERNAL duk_tval *duk_get_tval_or_unused(duk_hthread *thr, duk_idx_t idx) {
17898 	duk_tval *tv;
17899 
17900 	DUK_ASSERT_API_ENTRY(thr);
17901 
17902 	tv = duk_get_tval(thr, idx);
17903 	if (tv != NULL) {
17904 		return tv;
17905 	}
17906 	return (duk_tval *) DUK_LOSE_CONST(&duk__const_tval_unused);
17907 }
17908 
duk_require_tval(duk_hthread * thr,duk_idx_t idx)17909 DUK_INTERNAL duk_tval *duk_require_tval(duk_hthread *thr, duk_idx_t idx) {
17910 	duk_uidx_t vs_size;
17911 	duk_uidx_t uidx;
17912 
17913 	DUK_ASSERT_API_ENTRY(thr);
17914 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17915 
17916 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17917 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17918 	DUK_ASSERT_DISABLE(vs_size >= 0);  /* unsigned */
17919 
17920 	/* Use unsigned arithmetic to optimize comparison. */
17921 	if (idx < 0) {
17922 		uidx = vs_size + (duk_uidx_t) idx;
17923 	} else {
17924 		DUK_ASSERT(idx != DUK_INVALID_INDEX);
17925 		uidx = (duk_uidx_t) idx;
17926 	}
17927 
17928 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
17929 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
17930 
17931 	if (DUK_LIKELY(uidx < vs_size)) {
17932 		return thr->valstack_bottom + uidx;
17933 	}
17934 	DUK_ERROR_RANGE_INDEX(thr, idx);
17935 	DUK_WO_NORETURN(return NULL;);
17936 }
17937 
17938 /* Non-critical. */
duk_is_valid_index(duk_hthread * thr,duk_idx_t idx)17939 DUK_EXTERNAL duk_bool_t duk_is_valid_index(duk_hthread *thr, duk_idx_t idx) {
17940 	DUK_ASSERT_API_ENTRY(thr);
17941 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17942 
17943 	return (duk_normalize_index(thr, idx) >= 0);
17944 }
17945 
17946 /* Non-critical. */
duk_require_valid_index(duk_hthread * thr,duk_idx_t idx)17947 DUK_EXTERNAL void duk_require_valid_index(duk_hthread *thr, duk_idx_t idx) {
17948 	DUK_ASSERT_API_ENTRY(thr);
17949 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17950 
17951 	if (DUK_UNLIKELY(duk_normalize_index(thr, idx) < 0)) {
17952 		DUK_ERROR_RANGE_INDEX(thr, idx);
17953 		DUK_WO_NORETURN(return;);
17954 	}
17955 }
17956 
17957 /*
17958  *  Value stack top handling
17959  */
17960 
duk_get_top(duk_hthread * thr)17961 DUK_EXTERNAL duk_idx_t duk_get_top(duk_hthread *thr) {
17962 	DUK_ASSERT_API_ENTRY(thr);
17963 
17964 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
17965 }
17966 
17967 /* Internal helper to get current top but to require a minimum top value
17968  * (TypeError if not met).
17969  */
duk_get_top_require_min(duk_hthread * thr,duk_idx_t min_top)17970 DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_hthread *thr, duk_idx_t min_top) {
17971 	duk_idx_t ret;
17972 
17973 	DUK_ASSERT_API_ENTRY(thr);
17974 
17975 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
17976 	if (DUK_UNLIKELY(ret < min_top)) {
17977 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
17978 		DUK_WO_NORETURN(return 0;);
17979 	}
17980 	return ret;
17981 }
17982 
17983 /* Set stack top within currently allocated range, but don't reallocate.
17984  * This is performance critical especially for call handling, so whenever
17985  * changing, profile and look at generated code.
17986  */
duk_set_top(duk_hthread * thr,duk_idx_t idx)17987 DUK_EXTERNAL void duk_set_top(duk_hthread *thr, duk_idx_t idx) {
17988 	duk_uidx_t vs_size;
17989 	duk_uidx_t vs_limit;
17990 	duk_uidx_t uidx;
17991 	duk_tval *tv;
17992 
17993 	DUK_ASSERT_API_ENTRY(thr);
17994 	DUK_ASSERT(DUK_INVALID_INDEX < 0);
17995 
17996 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
17997 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
17998 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
17999 	vs_limit = (duk_uidx_t) (thr->valstack_end - thr->valstack_bottom);
18000 
18001 	if (idx < 0) {
18002 		/* Negative indices are always within allocated stack but
18003 		 * must not go below zero index.
18004 		 */
18005 		uidx = vs_size + (duk_uidx_t) idx;
18006 	} else {
18007 		/* Positive index can be higher than valstack top but must
18008 		 * not go above allocated stack (equality is OK).
18009 		 */
18010 		uidx = (duk_uidx_t) idx;
18011 	}
18012 
18013 	/* DUK_INVALID_INDEX won't be accepted as a valid index. */
18014 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_size);
18015 	DUK_ASSERT(vs_size + (duk_uidx_t) DUK_INVALID_INDEX >= vs_limit);
18016 
18017 #if defined(DUK_USE_VALSTACK_UNSAFE)
18018 	DUK_ASSERT(uidx <= vs_limit);
18019 	DUK_UNREF(vs_limit);
18020 #else
18021 	if (DUK_UNLIKELY(uidx > vs_limit)) {
18022 		DUK_ERROR_RANGE_INDEX(thr, idx);
18023 		DUK_WO_NORETURN(return;);
18024 	}
18025 #endif
18026 	DUK_ASSERT(uidx <= vs_limit);
18027 
18028 	/* Handle change in value stack top.  Respect value stack
18029 	 * initialization policy: 'undefined' above top.  Note that
18030 	 * DECREF may cause a side effect that reallocates valstack,
18031 	 * so must relookup after DECREF.
18032 	 */
18033 
18034 	if (uidx >= vs_size) {
18035 		/* Stack size increases or stays the same. */
18036 #if defined(DUK_USE_ASSERTIONS)
18037 		duk_uidx_t count;
18038 
18039 		count = uidx - vs_size;
18040 		while (count != 0) {
18041 			count--;
18042 			tv = thr->valstack_top + count;
18043 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18044 		}
18045 #endif
18046 		thr->valstack_top = thr->valstack_bottom + uidx;
18047 	} else {
18048 		/* Stack size decreases. */
18049 #if defined(DUK_USE_REFERENCE_COUNTING)
18050 		duk_uidx_t count;
18051 		duk_tval *tv_end;
18052 
18053 		count = vs_size - uidx;
18054 		DUK_ASSERT(count > 0);
18055 		tv = thr->valstack_top;
18056 		tv_end = tv - count;
18057 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18058 		do {
18059 			tv--;
18060 			DUK_ASSERT(tv >= thr->valstack_bottom);
18061 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18062 		} while (tv != tv_end);
18063 		thr->valstack_top = tv_end;
18064 		DUK_REFZERO_CHECK_FAST(thr);
18065 #else  /* DUK_USE_REFERENCE_COUNTING */
18066 		duk_uidx_t count;
18067 		duk_tval *tv_end;
18068 
18069 		count = vs_size - uidx;
18070 		tv = thr->valstack_top;
18071 		tv_end = tv - count;
18072 		DUK_ASSERT(tv > tv_end);
18073 		do {
18074 			tv--;
18075 			DUK_TVAL_SET_UNDEFINED(tv);
18076 		} while (tv != tv_end);
18077 		thr->valstack_top = tv_end;
18078 #endif  /* DUK_USE_REFERENCE_COUNTING */
18079 	}
18080 }
18081 
18082 /* Internal variant with a non-negative index and no runtime size checks. */
18083 #if defined(DUK_USE_PREFER_SIZE)
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18084 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18085 	DUK_ASSERT_API_ENTRY(thr);
18086 
18087 	duk_set_top(thr, idx);
18088 }
18089 #else  /* DUK_USE_PREFER_SIZE */
duk_set_top_unsafe(duk_hthread * thr,duk_idx_t idx)18090 DUK_INTERNAL void duk_set_top_unsafe(duk_hthread *thr, duk_idx_t idx) {
18091 	duk_uidx_t uidx;
18092 	duk_uidx_t vs_size;
18093 	duk_tval *tv;
18094 
18095 	DUK_ASSERT_API_ENTRY(thr);
18096 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18097 	DUK_ASSERT(thr->valstack_end >= thr->valstack_bottom);
18098 	DUK_ASSERT(idx >= 0);
18099 	DUK_ASSERT(idx <= (duk_idx_t) (thr->valstack_end - thr->valstack_bottom));
18100 
18101 	/* XXX: byte arithmetic */
18102 	uidx = (duk_uidx_t) idx;
18103 	vs_size = (duk_uidx_t) (thr->valstack_top - thr->valstack_bottom);
18104 
18105 	if (uidx >= vs_size) {
18106 		/* Stack size increases or stays the same. */
18107 #if defined(DUK_USE_ASSERTIONS)
18108 		duk_uidx_t count;
18109 
18110 		count = uidx - vs_size;
18111 		while (count != 0) {
18112 			count--;
18113 			tv = thr->valstack_top + count;
18114 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
18115 		}
18116 #endif
18117 		thr->valstack_top = thr->valstack_bottom + uidx;
18118 	} else {
18119 		/* Stack size decreases. */
18120 #if defined(DUK_USE_REFERENCE_COUNTING)
18121 		duk_uidx_t count;
18122 		duk_tval *tv_end;
18123 
18124 		count = vs_size - uidx;
18125 		DUK_ASSERT(count > 0);
18126 		tv = thr->valstack_top;
18127 		tv_end = tv - count;
18128 		DUK_ASSERT(tv > tv_end);  /* Because count > 0. */
18129 		do {
18130 			tv--;
18131 			DUK_ASSERT(tv >= thr->valstack_bottom);
18132 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
18133 		} while (tv != tv_end);
18134 		thr->valstack_top = tv_end;
18135 		DUK_REFZERO_CHECK_FAST(thr);
18136 #else  /* DUK_USE_REFERENCE_COUNTING */
18137 		duk_uidx_t count;
18138 		duk_tval *tv_end;
18139 
18140 		count = vs_size - uidx;
18141 		tv = thr->valstack_top;
18142 		tv_end = tv - count;
18143 		DUK_ASSERT(tv > tv_end);
18144 		do {
18145 			tv--;
18146 			DUK_TVAL_SET_UNDEFINED(tv);
18147 		} while (tv != tv_end);
18148 		thr->valstack_top = tv_end;
18149 #endif  /* DUK_USE_REFERENCE_COUNTING */
18150 	}
18151 }
18152 #endif  /* DUK_USE_PREFER_SIZE */
18153 
18154 /* Internal helper: set top to 'top', and set [idx_wipe_start,top[ to
18155  * 'undefined' (doing nothing if idx_wipe_start == top).  Indices are
18156  * positive and within value stack reserve.  This is used by call handling.
18157  */
duk_set_top_and_wipe(duk_hthread * thr,duk_idx_t top,duk_idx_t idx_wipe_start)18158 DUK_INTERNAL void duk_set_top_and_wipe(duk_hthread *thr, duk_idx_t top, duk_idx_t idx_wipe_start) {
18159 	DUK_ASSERT_API_ENTRY(thr);
18160 	DUK_ASSERT(top >= 0);
18161 	DUK_ASSERT(idx_wipe_start >= 0);
18162 	DUK_ASSERT(idx_wipe_start <= top);
18163 	DUK_ASSERT(thr->valstack_bottom + top <= thr->valstack_end);
18164 	DUK_ASSERT(thr->valstack_bottom + idx_wipe_start <= thr->valstack_end);
18165 
18166 	duk_set_top_unsafe(thr, idx_wipe_start);
18167 	duk_set_top_unsafe(thr, top);
18168 }
18169 
duk_get_top_index(duk_hthread * thr)18170 DUK_EXTERNAL duk_idx_t duk_get_top_index(duk_hthread *thr) {
18171 	duk_idx_t ret;
18172 
18173 	DUK_ASSERT_API_ENTRY(thr);
18174 
18175 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18176 	if (DUK_UNLIKELY(ret < 0)) {
18177 		/* Return invalid index; if caller uses this without checking
18178 		 * in another API call, the index won't map to a valid stack
18179 		 * entry.
18180 		 */
18181 		return DUK_INVALID_INDEX;
18182 	}
18183 	return ret;
18184 }
18185 
18186 /* Internal variant: call assumes there is at least one element on the value
18187  * stack frame; this is only asserted for.
18188  */
duk_get_top_index_unsafe(duk_hthread * thr)18189 DUK_INTERNAL duk_idx_t duk_get_top_index_unsafe(duk_hthread *thr) {
18190 	duk_idx_t ret;
18191 
18192 	DUK_ASSERT_API_ENTRY(thr);
18193 
18194 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18195 	return ret;
18196 }
18197 
duk_require_top_index(duk_hthread * thr)18198 DUK_EXTERNAL duk_idx_t duk_require_top_index(duk_hthread *thr) {
18199 	duk_idx_t ret;
18200 
18201 	DUK_ASSERT_API_ENTRY(thr);
18202 
18203 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom) - 1;
18204 	if (DUK_UNLIKELY(ret < 0)) {
18205 		DUK_ERROR_RANGE_INDEX(thr, -1);
18206 		DUK_WO_NORETURN(return 0;);
18207 	}
18208 	return ret;
18209 }
18210 
18211 /*
18212  *  Value stack resizing.
18213  *
18214  *  This resizing happens above the current "top": the value stack can be
18215  *  grown or shrunk, but the "top" is not affected.  The value stack cannot
18216  *  be resized to a size below the current reserve.
18217  *
18218  *  The low level reallocation primitive must carefully recompute all value
18219  *  stack pointers, and must also work if ALL pointers are NULL.  The resize
18220  *  is quite tricky because the valstack realloc may cause a mark-and-sweep,
18221  *  which may run finalizers.  Running finalizers may resize the valstack
18222  *  recursively (the same value stack we're working on).  So, after realloc
18223  *  returns, we know that the valstack bottom, top, and reserve should still
18224  *  be the same (there should not be live values above the "top"), but its
18225  *  underlying size, alloc_end, and base pointer may have changed.
18226  *
18227  *  'new_size' is known to be <= DUK_USE_VALSTACK_LIMIT, which ensures that
18228  *  size_t and pointer arithmetic won't wrap in duk__resize_valstack().
18229  */
18230 
18231 /* Low level valstack resize primitive, used for both grow and shrink.  All
18232  * adjustments for slack etc have already been done.  Doesn't throw but does
18233  * have allocation side effects.
18234  */
duk__resize_valstack(duk_hthread * thr,duk_size_t new_size)18235 DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__resize_valstack(duk_hthread *thr, duk_size_t new_size) {
18236 	duk_tval *pre_valstack;
18237 	duk_tval *pre_bottom;
18238 	duk_tval *pre_top;
18239 	duk_tval *pre_end;
18240 	duk_tval *pre_alloc_end;
18241 	duk_ptrdiff_t ptr_diff;
18242 	duk_tval *new_valstack;
18243 	duk_size_t new_alloc_size;
18244 	duk_tval *tv_prev_alloc_end;
18245 	duk_tval *p;
18246 
18247 	DUK_ASSERT_HTHREAD_VALID(thr);
18248 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18249 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18250 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18251 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18252 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) <= new_size);  /* can't resize below 'top' */
18253 	DUK_ASSERT(new_size <= DUK_USE_VALSTACK_LIMIT);  /* valstack limit caller has check, prevents wrapping */
18254 	DUK_ASSERT(new_size <= DUK_SIZE_MAX / sizeof(duk_tval));  /* specific assert for wrapping */
18255 
18256 	/* Pre-realloc pointer copies for asserts and debug logs. */
18257 	pre_valstack = thr->valstack;
18258 	pre_bottom = thr->valstack_bottom;
18259 	pre_top = thr->valstack_top;
18260 	pre_end = thr->valstack_end;
18261 	pre_alloc_end = thr->valstack_alloc_end;
18262 
18263 	DUK_UNREF(pre_valstack);
18264 	DUK_UNREF(pre_bottom);
18265 	DUK_UNREF(pre_top);
18266 	DUK_UNREF(pre_end);
18267 	DUK_UNREF(pre_alloc_end);
18268 
18269 	/* If finalizer torture enabled, force base pointer change every time
18270 	 * when it would be allowed.
18271 	 */
18272 #if defined(DUK_USE_FINALIZER_TORTURE)
18273 	if (thr->heap->pf_prevent_count == 0) {
18274 		duk_hthread_valstack_torture_realloc(thr);
18275 	}
18276 #endif
18277 
18278 	/* Allocate a new valstack using DUK_REALLOC_DIRECT() to deal with
18279 	 * a side effect changing the base pointer.
18280 	 */
18281 	new_alloc_size = sizeof(duk_tval) * new_size;
18282 	new_valstack = (duk_tval *) DUK_REALLOC_INDIRECT(thr->heap, duk_hthread_get_valstack_ptr, (void *) thr, new_alloc_size);
18283 	if (DUK_UNLIKELY(new_valstack == NULL)) {
18284 		/* Because new_size != 0, if condition doesn't need to be
18285 		 * (new_valstack != NULL || new_size == 0).
18286 		 */
18287 		DUK_ASSERT(new_size != 0);
18288 		DUK_D(DUK_DPRINT("failed to resize valstack to %lu entries (%lu bytes)",
18289 		                 (unsigned long) new_size, (unsigned long) new_alloc_size));
18290 		return 0;
18291 	}
18292 
18293 	/* Debug log any changes in pointer(s) by side effects.  These don't
18294 	 * necessarily imply any incorrect behavior, but should be rare in
18295 	 * practice.
18296 	 */
18297 #if defined(DUK_USE_DEBUG)
18298 	if (thr->valstack != pre_valstack) {
18299 		DUK_D(DUK_DPRINT("valstack base pointer changed during valstack resize: %p -> %p",
18300 		                 (void *) pre_valstack, (void *) thr->valstack));
18301 	}
18302 	if (thr->valstack_bottom != pre_bottom) {
18303 		DUK_D(DUK_DPRINT("valstack bottom pointer changed during valstack resize: %p -> %p",
18304 		                 (void *) pre_bottom, (void *) thr->valstack_bottom));
18305 	}
18306 	if (thr->valstack_top != pre_top) {
18307 		DUK_D(DUK_DPRINT("valstack top pointer changed during valstack resize: %p -> %p",
18308 		                 (void *) pre_top, (void *) thr->valstack_top));
18309 	}
18310 	if (thr->valstack_end != pre_end) {
18311 		DUK_D(DUK_DPRINT("valstack end pointer changed during valstack resize: %p -> %p",
18312 		                 (void *) pre_end, (void *) thr->valstack_end));
18313 	}
18314 	if (thr->valstack_alloc_end != pre_alloc_end) {
18315 		DUK_D(DUK_DPRINT("valstack alloc_end pointer changed during valstack resize: %p -> %p",
18316 		                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end));
18317 	}
18318 #endif
18319 
18320 	/* Assertions: offsets for bottom, top, and end (reserve) must not
18321 	 * have changed even with side effects because they are always
18322 	 * restored in unwind.  For alloc_end there's no guarantee: it may
18323 	 * have grown or shrunk (but remain above 'end').
18324 	 */
18325 	DUK_ASSERT(thr->valstack_bottom - thr->valstack == pre_bottom - pre_valstack);
18326 	DUK_ASSERT(thr->valstack_top - thr->valstack == pre_top - pre_valstack);
18327 	DUK_ASSERT(thr->valstack_end - thr->valstack == pre_end - pre_valstack);
18328 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18329 
18330 	/* Write new pointers.  Most pointers can be handled as a pointer
18331 	 * difference.
18332 	 */
18333 	ptr_diff = (duk_ptrdiff_t) ((duk_uint8_t *) new_valstack - (duk_uint8_t *) thr->valstack);
18334 	tv_prev_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_alloc_end + ptr_diff);
18335 	thr->valstack = new_valstack;
18336 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + ptr_diff);
18337 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + ptr_diff);
18338 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_end + ptr_diff);
18339 	thr->valstack_alloc_end = (duk_tval *) (void *) ((duk_uint8_t *) new_valstack + new_alloc_size);
18340 
18341 	/* Assertions: pointer sanity after pointer updates. */
18342 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
18343 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
18344 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
18345 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18346 
18347 	DUK_D(DUK_DPRINT("resized valstack %lu -> %lu elements (%lu -> %lu bytes): "
18348 	                 "base=%p -> %p, bottom=%p -> %p (%ld), top=%p -> %p (%ld), "
18349 	                 "end=%p -> %p (%ld), alloc_end=%p -> %p (%ld);"
18350 	                 " tv_prev_alloc_end=%p (-> %ld inits; <0 means shrink)",
18351 	                 (unsigned long) (pre_alloc_end - pre_valstack),
18352 	                 (unsigned long) new_size,
18353 	                 (unsigned long) ((duk_uint8_t *) pre_alloc_end - (duk_uint8_t *) pre_valstack),
18354 	                 (unsigned long) new_alloc_size,
18355 	                 (void *) pre_valstack, (void *) thr->valstack,
18356 	                 (void *) pre_bottom, (void *) thr->valstack_bottom, (long) (thr->valstack_bottom - thr->valstack),
18357 	                 (void *) pre_top, (void *) thr->valstack_top, (long) (thr->valstack_top - thr->valstack),
18358 	                 (void *) pre_end, (void *) thr->valstack_end, (long) (thr->valstack_end - thr->valstack),
18359 	                 (void *) pre_alloc_end, (void *) thr->valstack_alloc_end, (long) (thr->valstack_alloc_end - thr->valstack),
18360 	                 (void *) tv_prev_alloc_end, (long) (thr->valstack_alloc_end - tv_prev_alloc_end)));
18361 
18362 	/* If allocation grew, init any new slots to 'undefined'. */
18363 	p = tv_prev_alloc_end;
18364 	while (p < thr->valstack_alloc_end) {
18365 		/* Never executed if new size is smaller. */
18366 		DUK_TVAL_SET_UNDEFINED(p);
18367 		p++;
18368 	}
18369 
18370 	/* Assert for value stack initialization policy. */
18371 #if defined(DUK_USE_ASSERTIONS)
18372 	p = thr->valstack_top;
18373 	while (p < thr->valstack_alloc_end) {
18374 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(p));
18375 		p++;
18376 	}
18377 #endif
18378 
18379 	return 1;
18380 }
18381 
duk__valstack_grow(duk_hthread * thr,duk_size_t min_bytes,duk_bool_t throw_on_error)18382 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) {
18383 	duk_size_t min_size;
18384 	duk_size_t new_size;
18385 
18386 	DUK_ASSERT(min_bytes / sizeof(duk_tval) * sizeof(duk_tval) == min_bytes);
18387 	min_size = min_bytes / sizeof(duk_tval);  /* from bytes to slots */
18388 
18389 #if defined(DUK_USE_VALSTACK_GROW_SHIFT)
18390 	/* New size is minimum size plus a proportional slack, e.g. shift of
18391 	 * 2 means a 25% slack.
18392 	 */
18393 	new_size = min_size + (min_size >> DUK_USE_VALSTACK_GROW_SHIFT);
18394 #else
18395 	/* New size is tight with no slack.  This is sometimes preferred in
18396 	 * low memory environments.
18397 	 */
18398 	new_size = min_size;
18399 #endif
18400 
18401 	if (DUK_UNLIKELY(new_size > DUK_USE_VALSTACK_LIMIT || new_size < min_size /*wrap*/)) {
18402 		/* Note: may be triggered even if minimal new_size would not reach the limit,
18403 		 * plan limit accordingly.
18404 		 */
18405 		if (throw_on_error) {
18406 			DUK_ERROR_RANGE(thr, DUK_STR_VALSTACK_LIMIT);
18407 			DUK_WO_NORETURN(return 0;);
18408 		}
18409 		return 0;
18410 	}
18411 
18412 	if (duk__resize_valstack(thr, new_size) == 0) {
18413 		if (throw_on_error) {
18414 			DUK_ERROR_ALLOC_FAILED(thr);
18415 			DUK_WO_NORETURN(return 0;);
18416 		}
18417 		return 0;
18418 	}
18419 
18420 	thr->valstack_end = thr->valstack + min_size;
18421 	DUK_ASSERT(thr->valstack_alloc_end >= thr->valstack_end);
18422 
18423 	return 1;
18424 }
18425 
18426 /* Hot, inlined value stack grow check.  Because value stack almost never
18427  * grows, the actual resize call is in a NOINLINE helper.
18428  */
duk_valstack_grow_check_throw(duk_hthread * thr,duk_size_t min_bytes)18429 DUK_INTERNAL DUK_INLINE void duk_valstack_grow_check_throw(duk_hthread *thr, duk_size_t min_bytes) {
18430 	duk_tval *tv;
18431 
18432 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18433 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18434 		return;
18435 	}
18436 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18437 		/* Values in [valstack_top,valstack_alloc_end[ are initialized
18438 		 * to 'undefined' so we can just move the end pointer.
18439 		 */
18440 		thr->valstack_end = tv;
18441 		return;
18442 	}
18443 	(void) duk__valstack_grow(thr, min_bytes, 1 /*throw_on_error*/);
18444 }
18445 
18446 /* Hot, inlined value stack grow check which doesn't throw. */
duk_valstack_grow_check_nothrow(duk_hthread * thr,duk_size_t min_bytes)18447 DUK_INTERNAL DUK_INLINE duk_bool_t duk_valstack_grow_check_nothrow(duk_hthread *thr, duk_size_t min_bytes) {
18448 	duk_tval *tv;
18449 
18450 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + min_bytes);
18451 	if (DUK_LIKELY(thr->valstack_end >= tv)) {
18452 		return 1;
18453 	}
18454 	if (DUK_LIKELY(thr->valstack_alloc_end >= tv)) {
18455 		thr->valstack_end = tv;
18456 		return 1;
18457 	}
18458 	return duk__valstack_grow(thr, min_bytes, 0 /*throw_on_error*/);
18459 }
18460 
18461 /* Value stack shrink check, called from mark-and-sweep. */
duk_valstack_shrink_check_nothrow(duk_hthread * thr,duk_bool_t snug)18462 DUK_INTERNAL void duk_valstack_shrink_check_nothrow(duk_hthread *thr, duk_bool_t snug) {
18463 	duk_size_t alloc_bytes;
18464 	duk_size_t reserve_bytes;
18465 	duk_size_t shrink_bytes;
18466 
18467 	alloc_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
18468 	reserve_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
18469 	DUK_ASSERT(alloc_bytes >= reserve_bytes);
18470 
18471 	/* We're free to shrink the value stack allocation down to
18472 	 * reserve_bytes but not more.  If 'snug' (emergency GC)
18473 	 * shrink whatever we can.  Otherwise only shrink if the new
18474 	 * size would be considerably smaller.
18475 	 */
18476 
18477 #if defined(DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT)
18478 	if (snug) {
18479 		shrink_bytes = reserve_bytes;
18480 	} else {
18481 		duk_size_t proportion, slack;
18482 
18483 		/* Require that value stack shrinks by at least X% of its
18484 		 * current size.  For example, shift of 2 means at least
18485 		 * 25%.  The proportion is computed as bytes and may not
18486 		 * be a multiple of sizeof(duk_tval); that's OK here.
18487 		 */
18488 		proportion = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT;
18489 		if (alloc_bytes - reserve_bytes < proportion) {
18490 			/* Too little would be freed, do nothing. */
18491 			return;
18492 		}
18493 
18494 		/* Keep a slack after shrinking.  The slack is again a
18495 		 * proportion of the current size (the proportion should
18496 		 * of course be smaller than the check proportion above).
18497 		 */
18498 #if defined(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT)
18499 		DUK_ASSERT(DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT > DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT);
18500 		slack = alloc_bytes >> DUK_USE_VALSTACK_SHRINK_SLACK_SHIFT;
18501 #else
18502 		slack = 0;
18503 #endif
18504 		shrink_bytes = reserve_bytes +
18505 		               slack / sizeof(duk_tval) * sizeof(duk_tval);  /* multiple of duk_tval */
18506 	}
18507 #else  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18508 	/* Always snug, useful in some low memory environments. */
18509 	DUK_UNREF(snug);
18510 	shrink_bytes = reserve_bytes;
18511 #endif  /* DUK_USE_VALSTACK_SHRINK_CHECK_SHIFT */
18512 
18513 	DUK_D(DUK_DPRINT("valstack shrink check: alloc_bytes=%ld, reserve_bytes=%ld, shrink_bytes=%ld (unvalidated)",
18514 	                 (long) alloc_bytes, (long) reserve_bytes, (long) shrink_bytes));
18515 	DUK_ASSERT(shrink_bytes >= reserve_bytes);
18516 	if (shrink_bytes >= alloc_bytes) {
18517 		/* Skip if shrink target is same as current one (or higher,
18518 		 * though that shouldn't happen in practice).
18519 		 */
18520 		return;
18521 	}
18522 	DUK_ASSERT(shrink_bytes / sizeof(duk_tval) * sizeof(duk_tval) == shrink_bytes);
18523 
18524 	DUK_D(DUK_DPRINT("valstack shrink check: decided to shrink, snug: %ld", (long) snug));
18525 
18526 	duk__resize_valstack(thr, shrink_bytes / sizeof(duk_tval));
18527 }
18528 
duk_check_stack(duk_hthread * thr,duk_idx_t extra)18529 DUK_EXTERNAL duk_bool_t duk_check_stack(duk_hthread *thr, duk_idx_t extra) {
18530 	duk_size_t min_new_bytes;
18531 
18532 	DUK_ASSERT_API_ENTRY(thr);
18533 	DUK_ASSERT(thr != NULL);
18534 
18535 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18536 		if (extra < 0) {
18537 			/* Clamping to zero makes the API more robust to calling code
18538 			 * calculation errors.
18539 			 */
18540 			extra = 0;
18541 		} else {
18542 			/* Cause grow check to fail without wrapping arithmetic. */
18543 			extra = DUK_USE_VALSTACK_LIMIT;
18544 		}
18545 	}
18546 
18547 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18548 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18549 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18550 }
18551 
duk_require_stack(duk_hthread * thr,duk_idx_t extra)18552 DUK_EXTERNAL void duk_require_stack(duk_hthread *thr, duk_idx_t extra) {
18553 	duk_size_t min_new_bytes;
18554 
18555 	DUK_ASSERT_API_ENTRY(thr);
18556 	DUK_ASSERT(thr != NULL);
18557 
18558 	if (DUK_UNLIKELY(extra < 0 || extra > DUK_USE_VALSTACK_LIMIT)) {
18559 		if (extra < 0) {
18560 			/* Clamping to zero makes the API more robust to calling code
18561 			 * calculation errors.
18562 			 */
18563 			extra = 0;
18564 		} else {
18565 			/* Cause grow check to fail without wrapping arithmetic. */
18566 			extra = DUK_USE_VALSTACK_LIMIT;
18567 		}
18568 	}
18569 
18570 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack) +
18571 	                sizeof(duk_tval) * ((duk_size_t) extra + DUK_VALSTACK_INTERNAL_EXTRA);
18572 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18573 }
18574 
duk_check_stack_top(duk_hthread * thr,duk_idx_t top)18575 DUK_EXTERNAL duk_bool_t duk_check_stack_top(duk_hthread *thr, duk_idx_t top) {
18576 	duk_size_t min_new_bytes;
18577 
18578 	DUK_ASSERT_API_ENTRY(thr);
18579 
18580 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18581 		if (top < 0) {
18582 			/* Clamping to zero makes the API more robust to calling code
18583 			 * calculation errors.
18584 			 */
18585 			top = 0;
18586 		} else {
18587 			/* Cause grow check to fail without wrapping arithmetic. */
18588 			top = DUK_USE_VALSTACK_LIMIT;
18589 		}
18590 	}
18591 
18592 	DUK_ASSERT(top >= 0);
18593 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18594 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18595 	return duk_valstack_grow_check_nothrow(thr, min_new_bytes);
18596 }
18597 
duk_require_stack_top(duk_hthread * thr,duk_idx_t top)18598 DUK_EXTERNAL void duk_require_stack_top(duk_hthread *thr, duk_idx_t top) {
18599 	duk_size_t min_new_bytes;
18600 
18601 	DUK_ASSERT_API_ENTRY(thr);
18602 
18603 	if (DUK_UNLIKELY(top < 0 || top > DUK_USE_VALSTACK_LIMIT)) {
18604 		if (top < 0) {
18605 			/* Clamping to zero makes the API more robust to calling code
18606 			 * calculation errors.
18607 			 */
18608 			top = 0;
18609 		} else {
18610 			/* Cause grow check to fail without wrapping arithmetic. */
18611 			top = DUK_USE_VALSTACK_LIMIT;
18612 		}
18613 	}
18614 
18615 	DUK_ASSERT(top >= 0);
18616 	min_new_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) +
18617 	                sizeof(duk_tval) * ((duk_size_t) top + DUK_VALSTACK_INTERNAL_EXTRA);
18618 	duk_valstack_grow_check_throw(thr, min_new_bytes);
18619 }
18620 
18621 /*
18622  *  Basic stack manipulation: swap, dup, insert, replace, etc
18623  */
18624 
duk_swap(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)18625 DUK_EXTERNAL void duk_swap(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
18626 	duk_tval *tv1;
18627 	duk_tval *tv2;
18628 	duk_tval tv_tmp;
18629 
18630 	DUK_ASSERT_API_ENTRY(thr);
18631 
18632 	tv1 = duk_require_tval(thr, idx1);
18633 	DUK_ASSERT(tv1 != NULL);
18634 	tv2 = duk_require_tval(thr, idx2);
18635 	DUK_ASSERT(tv2 != NULL);
18636 
18637 	/* If tv1==tv2 this is a NOP, no check is needed */
18638 	DUK_TVAL_SET_TVAL(&tv_tmp, tv1);
18639 	DUK_TVAL_SET_TVAL(tv1, tv2);
18640 	DUK_TVAL_SET_TVAL(tv2, &tv_tmp);
18641 }
18642 
duk_swap_top(duk_hthread * thr,duk_idx_t idx)18643 DUK_EXTERNAL void duk_swap_top(duk_hthread *thr, duk_idx_t idx) {
18644 	DUK_ASSERT_API_ENTRY(thr);
18645 
18646 	duk_swap(thr, idx, -1);
18647 }
18648 
duk_dup(duk_hthread * thr,duk_idx_t from_idx)18649 DUK_EXTERNAL void duk_dup(duk_hthread *thr, duk_idx_t from_idx) {
18650 	duk_tval *tv_from;
18651 	duk_tval *tv_to;
18652 
18653 	DUK_ASSERT_API_ENTRY(thr);
18654 	DUK__CHECK_SPACE();
18655 
18656 	tv_from = duk_require_tval(thr, from_idx);
18657 	tv_to = thr->valstack_top++;
18658 	DUK_ASSERT(tv_from != NULL);
18659 	DUK_ASSERT(tv_to != NULL);
18660 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18661 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18662 }
18663 
duk_dup_top(duk_hthread * thr)18664 DUK_EXTERNAL void duk_dup_top(duk_hthread *thr) {
18665 #if defined(DUK_USE_PREFER_SIZE)
18666 	duk_dup(thr, -1);
18667 #else
18668 	duk_tval *tv_from;
18669 	duk_tval *tv_to;
18670 
18671 	DUK_ASSERT_API_ENTRY(thr);
18672 	DUK__CHECK_SPACE();
18673 
18674 	if (DUK_UNLIKELY(thr->valstack_top - thr->valstack_bottom <= 0)) {
18675 		DUK_ERROR_RANGE_INDEX(thr, -1);
18676 		DUK_WO_NORETURN(return;);
18677 	}
18678 	tv_from = thr->valstack_top - 1;
18679 	tv_to = thr->valstack_top++;
18680 	DUK_ASSERT(tv_from != NULL);
18681 	DUK_ASSERT(tv_to != NULL);
18682 	DUK_TVAL_SET_TVAL(tv_to, tv_from);
18683 	DUK_TVAL_INCREF(thr, tv_to);  /* no side effects */
18684 #endif
18685 }
18686 
duk_dup_0(duk_hthread * thr)18687 DUK_INTERNAL void duk_dup_0(duk_hthread *thr) {
18688 	DUK_ASSERT_API_ENTRY(thr);
18689 	duk_dup(thr, 0);
18690 }
duk_dup_1(duk_hthread * thr)18691 DUK_INTERNAL void duk_dup_1(duk_hthread *thr) {
18692 	DUK_ASSERT_API_ENTRY(thr);
18693 	duk_dup(thr, 1);
18694 }
duk_dup_2(duk_hthread * thr)18695 DUK_INTERNAL void duk_dup_2(duk_hthread *thr) {
18696 	DUK_ASSERT_API_ENTRY(thr);
18697 	duk_dup(thr, 2);
18698 }
duk_dup_m2(duk_hthread * thr)18699 DUK_INTERNAL void duk_dup_m2(duk_hthread *thr) {
18700 	DUK_ASSERT_API_ENTRY(thr);
18701 	duk_dup(thr, -2);
18702 }
duk_dup_m3(duk_hthread * thr)18703 DUK_INTERNAL void duk_dup_m3(duk_hthread *thr) {
18704 	DUK_ASSERT_API_ENTRY(thr);
18705 	duk_dup(thr, -3);
18706 }
duk_dup_m4(duk_hthread * thr)18707 DUK_INTERNAL void duk_dup_m4(duk_hthread *thr) {
18708 	DUK_ASSERT_API_ENTRY(thr);
18709 	duk_dup(thr, -4);
18710 }
18711 
duk_insert(duk_hthread * thr,duk_idx_t to_idx)18712 DUK_EXTERNAL void duk_insert(duk_hthread *thr, duk_idx_t to_idx) {
18713 	duk_tval *p;
18714 	duk_tval *q;
18715 	duk_tval tv_tmp;
18716 	duk_size_t nbytes;
18717 
18718 	DUK_ASSERT_API_ENTRY(thr);
18719 
18720 	p = duk_require_tval(thr, to_idx);
18721 	DUK_ASSERT(p != NULL);
18722 	q = duk_require_tval(thr, -1);
18723 	DUK_ASSERT(q != NULL);
18724 
18725 	DUK_ASSERT(q >= p);
18726 
18727 	/*              nbytes
18728 	 *           <--------->
18729 	 *    [ ... | p | x | x | q ]
18730 	 * => [ ... | q | p | x | x ]
18731 	 */
18732 
18733 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18734 
18735 	DUK_DDD(DUK_DDDPRINT("duk_insert: to_idx=%ld, p=%p, q=%p, nbytes=%lu",
18736 	                     (long) to_idx, (void *) p, (void *) q, (unsigned long) nbytes));
18737 
18738 	/* No net refcount changes.  No need to special case nbytes == 0
18739 	 * (p == q).
18740 	 */
18741 	DUK_TVAL_SET_TVAL(&tv_tmp, q);
18742 	duk_memmove((void *) (p + 1), (const void *) p, (size_t) nbytes);
18743 	DUK_TVAL_SET_TVAL(p, &tv_tmp);
18744 }
18745 
duk_insert_undefined(duk_hthread * thr,duk_idx_t idx)18746 DUK_INTERNAL void duk_insert_undefined(duk_hthread *thr, duk_idx_t idx) {
18747 	DUK_ASSERT_API_ENTRY(thr);
18748 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices. */
18749 
18750 	duk_push_undefined(thr);
18751 	duk_insert(thr, idx);
18752 }
18753 
duk_insert_undefined_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18754 DUK_INTERNAL void duk_insert_undefined_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18755 	duk_tval *tv, *tv_end;
18756 
18757 	DUK_ASSERT_API_ENTRY(thr);
18758 	DUK_ASSERT(idx >= 0);  /* Doesn't support negative indices or count. */
18759 	DUK_ASSERT(count >= 0);
18760 
18761 	tv = duk_reserve_gap(thr, idx, count);
18762 	tv_end = tv + count;
18763 	while (tv != tv_end) {
18764 		DUK_TVAL_SET_UNDEFINED(tv);
18765 		tv++;
18766 	}
18767 }
18768 
duk_replace(duk_hthread * thr,duk_idx_t to_idx)18769 DUK_EXTERNAL void duk_replace(duk_hthread *thr, duk_idx_t to_idx) {
18770 	duk_tval *tv1;
18771 	duk_tval *tv2;
18772 	duk_tval tv_tmp;
18773 
18774 	DUK_ASSERT_API_ENTRY(thr);
18775 
18776 	tv1 = duk_require_tval(thr, -1);
18777 	DUK_ASSERT(tv1 != NULL);
18778 	tv2 = duk_require_tval(thr, to_idx);
18779 	DUK_ASSERT(tv2 != NULL);
18780 
18781 	/* For tv1 == tv2, both pointing to stack top, the end result
18782 	 * is same as duk_pop(thr).
18783 	 */
18784 	DUK_TVAL_SET_TVAL(&tv_tmp, tv2);
18785 	DUK_TVAL_SET_TVAL(tv2, tv1);
18786 	DUK_TVAL_SET_UNDEFINED(tv1);
18787 	thr->valstack_top--;
18788 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18789 }
18790 
duk_copy(duk_hthread * thr,duk_idx_t from_idx,duk_idx_t to_idx)18791 DUK_EXTERNAL void duk_copy(duk_hthread *thr, duk_idx_t from_idx, duk_idx_t to_idx) {
18792 	duk_tval *tv1;
18793 	duk_tval *tv2;
18794 
18795 	DUK_ASSERT_API_ENTRY(thr);
18796 
18797 	tv1 = duk_require_tval(thr, from_idx);
18798 	DUK_ASSERT(tv1 != NULL);
18799 	tv2 = duk_require_tval(thr, to_idx);
18800 	DUK_ASSERT(tv2 != NULL);
18801 
18802 	/* For tv1 == tv2, this is a no-op (no explicit check needed). */
18803 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv2, tv1);  /* side effects */
18804 }
18805 
duk_remove(duk_hthread * thr,duk_idx_t idx)18806 DUK_EXTERNAL void duk_remove(duk_hthread *thr, duk_idx_t idx) {
18807 	duk_tval *p;
18808 	duk_tval *q;
18809 #if defined(DUK_USE_REFERENCE_COUNTING)
18810 	duk_tval tv_tmp;
18811 #endif
18812 	duk_size_t nbytes;
18813 
18814 	DUK_ASSERT_API_ENTRY(thr);
18815 
18816 	p = duk_require_tval(thr, idx);
18817 	DUK_ASSERT(p != NULL);
18818 	q = duk_require_tval(thr, -1);
18819 	DUK_ASSERT(q != NULL);
18820 
18821 	DUK_ASSERT(q >= p);
18822 
18823 	/*              nbytes            zero size case
18824 	 *           <--------->
18825 	 *    [ ... | p | x | x | q ]     [ ... | p==q ]
18826 	 * => [ ... | x | x | q ]         [ ... ]
18827 	 */
18828 
18829 #if defined(DUK_USE_REFERENCE_COUNTING)
18830 	/* use a temp: decref only when valstack reachable values are correct */
18831 	DUK_TVAL_SET_TVAL(&tv_tmp, p);
18832 #endif
18833 
18834 	nbytes = (duk_size_t) (((duk_uint8_t *) q) - ((duk_uint8_t *) p));  /* Note: 'q' is top-1 */
18835 	duk_memmove((void *) p, (const void *) (p + 1), (size_t) nbytes);
18836 
18837 	DUK_TVAL_SET_UNDEFINED(q);
18838 	thr->valstack_top--;
18839 
18840 #if defined(DUK_USE_REFERENCE_COUNTING)
18841 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
18842 #endif
18843 }
18844 
duk_remove_unsafe(duk_hthread * thr,duk_idx_t idx)18845 DUK_INTERNAL void duk_remove_unsafe(duk_hthread *thr, duk_idx_t idx) {
18846 	DUK_ASSERT_API_ENTRY(thr);
18847 
18848 	duk_remove(thr, idx);  /* XXX: no optimization for now */
18849 }
18850 
duk_remove_m2(duk_hthread * thr)18851 DUK_INTERNAL void duk_remove_m2(duk_hthread *thr) {
18852 	DUK_ASSERT_API_ENTRY(thr);
18853 
18854 	duk_remove(thr, -2);
18855 }
18856 
duk_remove_n(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18857 DUK_INTERNAL void duk_remove_n(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18858 #if defined(DUK_USE_PREFER_SIZE)
18859 	/* XXX: maybe too slow even when preferring size? */
18860 	DUK_ASSERT_API_ENTRY(thr);
18861 	DUK_ASSERT(count >= 0);
18862 	DUK_ASSERT(idx >= 0);
18863 
18864 	while (count-- > 0) {
18865 		duk_remove(thr, idx);
18866 	}
18867 #else  /* DUK_USE_PREFER_SIZE */
18868 	duk_tval *tv_src;
18869 	duk_tval *tv_dst;
18870 	duk_tval *tv_newtop;
18871 	duk_tval *tv;
18872 	duk_size_t bytes;
18873 
18874 	DUK_ASSERT_API_ENTRY(thr);
18875 	DUK_ASSERT(count >= 0);
18876 	DUK_ASSERT(idx >= 0);
18877 
18878 	tv_dst = thr->valstack_bottom + idx;
18879 	DUK_ASSERT(tv_dst <= thr->valstack_top);
18880 	tv_src = tv_dst + count;
18881 	DUK_ASSERT(tv_src <= thr->valstack_top);
18882 	bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
18883 
18884 	for (tv = tv_dst; tv < tv_src; tv++) {
18885 		DUK_TVAL_DECREF_NORZ(thr, tv);
18886 	}
18887 
18888 	duk_memmove((void *) tv_dst, (const void *) tv_src, bytes);
18889 
18890 	tv_newtop = thr->valstack_top - count;
18891 	for (tv = tv_newtop; tv < thr->valstack_top; tv++) {
18892 		DUK_TVAL_SET_UNDEFINED(tv);
18893 	}
18894 	thr->valstack_top = tv_newtop;
18895 
18896 	/* When not preferring size, only NORZ macros are used; caller
18897 	 * is expected to DUK_REFZERO_CHECK().
18898 	 */
18899 #endif  /* DUK_USE_PREFER_SIZE */
18900 }
18901 
duk_remove_n_unsafe(duk_hthread * thr,duk_idx_t idx,duk_idx_t count)18902 DUK_INTERNAL void duk_remove_n_unsafe(duk_hthread *thr, duk_idx_t idx, duk_idx_t count) {
18903 	DUK_ASSERT_API_ENTRY(thr);
18904 
18905 	duk_remove_n(thr, idx, count);  /* XXX: no optimization for now */
18906 }
18907 
18908 /*
18909  *  Stack slice primitives
18910  */
18911 
duk_xcopymove_raw(duk_hthread * to_thr,duk_hthread * from_thr,duk_idx_t count,duk_bool_t is_copy)18912 DUK_EXTERNAL void duk_xcopymove_raw(duk_hthread *to_thr, duk_hthread *from_thr, duk_idx_t count, duk_bool_t is_copy) {
18913 	void *src;
18914 	duk_size_t nbytes;
18915 	duk_tval *p;
18916 	duk_tval *q;
18917 
18918 	/* XXX: several pointer comparison issues here */
18919 
18920 	DUK_ASSERT_API_ENTRY(to_thr);
18921 	DUK_ASSERT_CTX_VALID(to_thr);
18922 	DUK_ASSERT_CTX_VALID(from_thr);
18923 	DUK_ASSERT(to_thr->heap == from_thr->heap);
18924 
18925 	if (DUK_UNLIKELY(to_thr == from_thr)) {
18926 		DUK_ERROR_TYPE(to_thr, DUK_STR_INVALID_CONTEXT);
18927 		DUK_WO_NORETURN(return;);
18928 	}
18929 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) DUK_USE_VALSTACK_LIMIT)) {
18930 		/* Maximum value check ensures 'nbytes' won't wrap below.
18931 		 * Also handles negative count.
18932 		 */
18933 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
18934 		DUK_WO_NORETURN(return;);
18935 	}
18936 	DUK_ASSERT(count >= 0);
18937 
18938 	nbytes = sizeof(duk_tval) * (duk_size_t) count;
18939 	if (DUK_UNLIKELY(nbytes == 0)) {
18940 		return;
18941 	}
18942 	DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
18943 	if (DUK_UNLIKELY((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes)) {
18944 		DUK_ERROR_RANGE_PUSH_BEYOND(to_thr);
18945 		DUK_WO_NORETURN(return;);
18946 	}
18947 	src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
18948 	if (DUK_UNLIKELY(src < (void *) from_thr->valstack_bottom)) {
18949 		DUK_ERROR_RANGE_INVALID_COUNT(to_thr);
18950 		DUK_WO_NORETURN(return;);
18951 	}
18952 
18953 	/* Copy values (no overlap even if to_thr == from_thr; that's not
18954 	 * allowed now anyway).
18955 	 */
18956 	DUK_ASSERT(nbytes > 0);
18957 	duk_memcpy((void *) to_thr->valstack_top, (const void *) src, (size_t) nbytes);
18958 
18959 	p = to_thr->valstack_top;
18960 	to_thr->valstack_top = (duk_tval *) (void *) (((duk_uint8_t *) p) + nbytes);
18961 
18962 	if (is_copy) {
18963 		/* Incref copies, keep originals. */
18964 		q = to_thr->valstack_top;
18965 		while (p < q) {
18966 			DUK_TVAL_INCREF(to_thr, p);  /* no side effects */
18967 			p++;
18968 		}
18969 	} else {
18970 		/* No net refcount change. */
18971 		p = from_thr->valstack_top;
18972 		q = (duk_tval *) (void *) (((duk_uint8_t *) p) - nbytes);
18973 		from_thr->valstack_top = q;
18974 
18975 		while (p > q) {
18976 			p--;
18977 			DUK_TVAL_SET_UNDEFINED(p);
18978 			/* XXX: fast primitive to set a bunch of values to UNDEFINED */
18979 		}
18980 	}
18981 }
18982 
18983 /* Internal helper: reserve a gap of 'count' elements at 'idx_base' and return a
18984  * pointer to the gap.  Values in the gap are garbage and MUST be initialized by
18985  * the caller before any side effects may occur.  The caller must ensure there's
18986  * enough stack reserve for 'count' values.
18987  */
duk_reserve_gap(duk_hthread * thr,duk_idx_t idx_base,duk_idx_t count)18988 DUK_INTERNAL duk_tval *duk_reserve_gap(duk_hthread *thr, duk_idx_t idx_base, duk_idx_t count) {
18989 	duk_tval *tv_src;
18990 	duk_tval *tv_dst;
18991 	duk_size_t gap_bytes;
18992 	duk_size_t copy_bytes;
18993 
18994 	/* Caller is responsible for ensuring there's enough preallocated
18995 	 * value stack.
18996 	 */
18997 	DUK_ASSERT_API_ENTRY(thr);
18998 	DUK_ASSERT(count >= 0);
18999 	DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack_top) >= (duk_size_t) count);
19000 
19001 	tv_src = thr->valstack_bottom + idx_base;
19002 	gap_bytes = (duk_size_t) count * sizeof(duk_tval);
19003 	tv_dst = (duk_tval *) (void *) ((duk_uint8_t *) tv_src + gap_bytes);
19004 	copy_bytes = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) tv_src);
19005 	thr->valstack_top = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_top + gap_bytes);
19006 	duk_memmove((void *) tv_dst, (const void *) tv_src, copy_bytes);
19007 
19008 	/* Values in the gap are left as garbage: caller must fill them in
19009 	 * and INCREF them before any side effects.
19010 	 */
19011 	return tv_src;
19012 }
19013 
19014 /*
19015  *  Get/opt/require
19016  */
19017 
duk_require_undefined(duk_hthread * thr,duk_idx_t idx)19018 DUK_EXTERNAL void duk_require_undefined(duk_hthread *thr, duk_idx_t idx) {
19019 	duk_tval *tv;
19020 
19021 	DUK_ASSERT_API_ENTRY(thr);
19022 
19023 	tv = duk_get_tval_or_unused(thr, idx);
19024 	DUK_ASSERT(tv != NULL);
19025 	if (DUK_UNLIKELY(!DUK_TVAL_IS_UNDEFINED(tv))) {
19026 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "undefined", DUK_STR_NOT_UNDEFINED);
19027 		DUK_WO_NORETURN(return;);
19028 	}
19029 }
19030 
duk_require_null(duk_hthread * thr,duk_idx_t idx)19031 DUK_EXTERNAL void duk_require_null(duk_hthread *thr, duk_idx_t idx) {
19032 	duk_tval *tv;
19033 
19034 	DUK_ASSERT_API_ENTRY(thr);
19035 
19036 	tv = duk_get_tval_or_unused(thr, idx);
19037 	DUK_ASSERT(tv != NULL);
19038 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NULL(tv))) {
19039 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "null", DUK_STR_NOT_NULL);
19040 		DUK_WO_NORETURN(return;);
19041 	}
19042 }
19043 
duk__get_boolean_raw(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19044 DUK_LOCAL DUK_ALWAYS_INLINE duk_bool_t duk__get_boolean_raw(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19045 	duk_bool_t ret;
19046 	duk_tval *tv;
19047 
19048 	DUK_ASSERT_CTX_VALID(thr);
19049 
19050 	tv = duk_get_tval_or_unused(thr, idx);
19051 	DUK_ASSERT(tv != NULL);
19052 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
19053 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19054 		DUK_ASSERT(ret == 0 || ret == 1);
19055 	} else {
19056 		ret = def_value;
19057 		/* Not guaranteed to be 0 or 1. */
19058 	}
19059 
19060 	return ret;
19061 }
19062 
duk_get_boolean(duk_hthread * thr,duk_idx_t idx)19063 DUK_EXTERNAL duk_bool_t duk_get_boolean(duk_hthread *thr, duk_idx_t idx) {
19064 	DUK_ASSERT_API_ENTRY(thr);
19065 
19066 	return duk__get_boolean_raw(thr, idx, 0);  /* default: false */
19067 }
19068 
duk_get_boolean_default(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19069 DUK_EXTERNAL duk_bool_t duk_get_boolean_default(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19070 	DUK_ASSERT_API_ENTRY(thr);
19071 
19072 	return duk__get_boolean_raw(thr, idx, def_value);
19073 }
19074 
duk_require_boolean(duk_hthread * thr,duk_idx_t idx)19075 DUK_EXTERNAL duk_bool_t duk_require_boolean(duk_hthread *thr, duk_idx_t idx) {
19076 	duk_tval *tv;
19077 	duk_bool_t ret;
19078 
19079 	DUK_ASSERT_API_ENTRY(thr);
19080 
19081 	tv = duk_get_tval_or_unused(thr, idx);
19082 	DUK_ASSERT(tv != NULL);
19083 	if (DUK_LIKELY(DUK_TVAL_IS_BOOLEAN(tv))) {
19084 		ret = DUK_TVAL_GET_BOOLEAN(tv);
19085 		DUK_ASSERT(ret == 0 || ret == 1);
19086 		return ret;
19087 	} else {
19088 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "boolean", DUK_STR_NOT_BOOLEAN);
19089 		DUK_WO_NORETURN(return 0;);
19090 	}
19091 }
19092 
duk_opt_boolean(duk_hthread * thr,duk_idx_t idx,duk_bool_t def_value)19093 DUK_EXTERNAL duk_bool_t duk_opt_boolean(duk_hthread *thr, duk_idx_t idx, duk_bool_t def_value) {
19094 	DUK_ASSERT_API_ENTRY(thr);
19095 
19096 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19097 		return def_value;
19098 	}
19099 	return duk_require_boolean(thr, idx);
19100 }
19101 
duk__get_number_raw(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19102 DUK_LOCAL DUK_ALWAYS_INLINE duk_double_t duk__get_number_raw(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19103 	duk_double_union ret;
19104 	duk_tval *tv;
19105 
19106 	DUK_ASSERT_CTX_VALID(thr);
19107 
19108 	tv = duk_get_tval_or_unused(thr, idx);
19109 	DUK_ASSERT(tv != NULL);
19110 #if defined(DUK_USE_FASTINT)
19111 	if (DUK_TVAL_IS_FASTINT(tv)) {
19112 		ret.d = (duk_double_t) DUK_TVAL_GET_FASTINT(tv);  /* XXX: cast trick */
19113 	}
19114 	else
19115 #endif
19116 	if (DUK_TVAL_IS_DOUBLE(tv)) {
19117 		/* When using packed duk_tval, number must be in NaN-normalized form
19118 		 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19119 		 * duk_tval.
19120 		 */
19121 		ret.d = DUK_TVAL_GET_DOUBLE(tv);
19122 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19123 	} else {
19124 		ret.d = def_value;
19125 		/* Default value (including NaN) may not be normalized. */
19126 	}
19127 
19128 	return ret.d;
19129 }
19130 
duk_get_number(duk_hthread * thr,duk_idx_t idx)19131 DUK_EXTERNAL duk_double_t duk_get_number(duk_hthread *thr, duk_idx_t idx) {
19132 	DUK_ASSERT_API_ENTRY(thr);
19133 	return duk__get_number_raw(thr, idx, DUK_DOUBLE_NAN);  /* default: NaN */
19134 }
19135 
duk_get_number_default(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19136 DUK_EXTERNAL duk_double_t duk_get_number_default(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19137 	DUK_ASSERT_API_ENTRY(thr);
19138 	return duk__get_number_raw(thr, idx, def_value);
19139 }
19140 
duk_require_number(duk_hthread * thr,duk_idx_t idx)19141 DUK_EXTERNAL duk_double_t duk_require_number(duk_hthread *thr, duk_idx_t idx) {
19142 	duk_tval *tv;
19143 	duk_double_union ret;
19144 
19145 	DUK_ASSERT_API_ENTRY(thr);
19146 
19147 	tv = duk_get_tval_or_unused(thr, idx);
19148 	DUK_ASSERT(tv != NULL);
19149 	if (DUK_UNLIKELY(!DUK_TVAL_IS_NUMBER(tv))) {
19150 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "number", DUK_STR_NOT_NUMBER);
19151 		DUK_WO_NORETURN(return 0.0;);
19152 	}
19153 
19154 	ret.d = DUK_TVAL_GET_NUMBER(tv);
19155 
19156 	/* When using packed duk_tval, number must be in NaN-normalized form
19157 	 * for it to be a duk_tval, so no need to normalize.  NOP for unpacked
19158 	 * duk_tval.
19159 	 */
19160 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&ret));
19161 	return ret.d;
19162 }
19163 
duk_opt_number(duk_hthread * thr,duk_idx_t idx,duk_double_t def_value)19164 DUK_EXTERNAL duk_double_t duk_opt_number(duk_hthread *thr, duk_idx_t idx, duk_double_t def_value) {
19165 	DUK_ASSERT_API_ENTRY(thr);
19166 
19167 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19168 		/* User provided default is not NaN normalized. */
19169 		return def_value;
19170 	}
19171 	return duk_require_number(thr, idx);
19172 }
19173 
duk_get_int(duk_hthread * thr,duk_idx_t idx)19174 DUK_EXTERNAL duk_int_t duk_get_int(duk_hthread *thr, duk_idx_t idx) {
19175 	DUK_ASSERT_API_ENTRY(thr);
19176 
19177 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
19178 }
19179 
duk_get_uint(duk_hthread * thr,duk_idx_t idx)19180 DUK_EXTERNAL duk_uint_t duk_get_uint(duk_hthread *thr, duk_idx_t idx) {
19181 	DUK_ASSERT_API_ENTRY(thr);
19182 
19183 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
19184 }
19185 
duk_get_int_default(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19186 DUK_EXTERNAL duk_int_t duk_get_int_default(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19187 	DUK_ASSERT_API_ENTRY(thr);
19188 
19189 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, def_value, 0 /*require*/);
19190 }
19191 
duk_get_uint_default(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19192 DUK_EXTERNAL duk_uint_t duk_get_uint_default(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19193 	DUK_ASSERT_API_ENTRY(thr);
19194 
19195 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, def_value, 0 /*require*/);
19196 }
19197 
duk_require_int(duk_hthread * thr,duk_idx_t idx)19198 DUK_EXTERNAL duk_int_t duk_require_int(duk_hthread *thr, duk_idx_t idx) {
19199 	DUK_ASSERT_API_ENTRY(thr);
19200 
19201 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 1 /*require*/);
19202 }
19203 
duk_require_uint(duk_hthread * thr,duk_idx_t idx)19204 DUK_EXTERNAL duk_uint_t duk_require_uint(duk_hthread *thr, duk_idx_t idx) {
19205 	DUK_ASSERT_API_ENTRY(thr);
19206 
19207 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 1 /*require*/);
19208 }
19209 
duk_opt_int(duk_hthread * thr,duk_idx_t idx,duk_int_t def_value)19210 DUK_EXTERNAL duk_int_t duk_opt_int(duk_hthread *thr, duk_idx_t idx, duk_int_t def_value) {
19211 	DUK_ASSERT_API_ENTRY(thr);
19212 
19213 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19214 		return def_value;
19215 	}
19216 	return duk_require_int(thr, idx);
19217 }
19218 
duk_opt_uint(duk_hthread * thr,duk_idx_t idx,duk_uint_t def_value)19219 DUK_EXTERNAL duk_uint_t duk_opt_uint(duk_hthread *thr, duk_idx_t idx, duk_uint_t def_value) {
19220 	DUK_ASSERT_API_ENTRY(thr);
19221 
19222 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19223 		return def_value;
19224 	}
19225 	return duk_require_uint(thr, idx);
19226 }
19227 
duk_get_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19228 DUK_EXTERNAL const char *duk_get_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19229 	duk_hstring *h;
19230 	const char *ret;
19231 	duk_size_t len;
19232 
19233 	DUK_ASSERT_API_ENTRY(thr);
19234 
19235 	h = duk_get_hstring(thr, idx);
19236 	if (h != NULL) {
19237 		len = DUK_HSTRING_GET_BYTELEN(h);
19238 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19239 	} else {
19240 		len = 0;
19241 		ret = NULL;
19242 	}
19243 
19244 	if (out_len != NULL) {
19245 		*out_len = len;
19246 	}
19247 	return ret;
19248 }
19249 
duk_require_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19250 DUK_EXTERNAL const char *duk_require_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19251 	duk_hstring *h;
19252 
19253 	DUK_ASSERT_API_ENTRY(thr);
19254 
19255 	h = duk_require_hstring(thr, idx);
19256 	DUK_ASSERT(h != NULL);
19257 	if (out_len) {
19258 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19259 	}
19260 	return (const char *) DUK_HSTRING_GET_DATA(h);
19261 }
19262 
duk_require_lstring_notsymbol(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)19263 DUK_INTERNAL const char *duk_require_lstring_notsymbol(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
19264 	duk_hstring *h;
19265 
19266 	DUK_ASSERT_API_ENTRY(thr);
19267 
19268 	h = duk_require_hstring_notsymbol(thr, idx);
19269 	DUK_ASSERT(h != NULL);
19270 	if (out_len) {
19271 		*out_len = DUK_HSTRING_GET_BYTELEN(h);
19272 	}
19273 	return (const char *) DUK_HSTRING_GET_DATA(h);
19274 }
19275 
duk_get_string(duk_hthread * thr,duk_idx_t idx)19276 DUK_EXTERNAL const char *duk_get_string(duk_hthread *thr, duk_idx_t idx) {
19277 	duk_hstring *h;
19278 
19279 	DUK_ASSERT_API_ENTRY(thr);
19280 
19281 	h = duk_get_hstring(thr, idx);
19282 	if (h != NULL) {
19283 		return (const char *) DUK_HSTRING_GET_DATA(h);
19284 	} else {
19285 		return NULL;
19286 	}
19287 }
19288 
duk_opt_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len,const char * def_ptr,duk_size_t def_len)19289 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) {
19290 	DUK_ASSERT_API_ENTRY(thr);
19291 
19292 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19293 		if (out_len != NULL) {
19294 			*out_len = def_len;
19295 		}
19296 		return def_ptr;
19297 	}
19298 	return duk_require_lstring(thr, idx, out_len);
19299 }
19300 
duk_opt_string(duk_hthread * thr,duk_idx_t idx,const char * def_ptr)19301 DUK_EXTERNAL const char *duk_opt_string(duk_hthread *thr, duk_idx_t idx, const char *def_ptr) {
19302 	DUK_ASSERT_API_ENTRY(thr);
19303 
19304 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19305 		return def_ptr;
19306 	}
19307 	return duk_require_string(thr, idx);
19308 }
19309 
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)19310 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) {
19311 	duk_hstring *h;
19312 	const char *ret;
19313 	duk_size_t len;
19314 
19315 	DUK_ASSERT_API_ENTRY(thr);
19316 
19317 	h = duk_get_hstring(thr, idx);
19318 	if (h != NULL) {
19319 		len = DUK_HSTRING_GET_BYTELEN(h);
19320 		ret = (const char *) DUK_HSTRING_GET_DATA(h);
19321 	} else {
19322 		len = def_len;
19323 		ret = def_ptr;
19324 	}
19325 
19326 	if (out_len != NULL) {
19327 		*out_len = len;
19328 	}
19329 	return ret;
19330 }
19331 
duk_get_string_default(duk_hthread * thr,duk_idx_t idx,const char * def_value)19332 DUK_EXTERNAL const char *duk_get_string_default(duk_hthread *thr, duk_idx_t idx, const char *def_value) {
19333 	duk_hstring *h;
19334 
19335 	DUK_ASSERT_API_ENTRY(thr);
19336 
19337 	h = duk_get_hstring(thr, idx);
19338 	if (h != NULL) {
19339 		return (const char *) DUK_HSTRING_GET_DATA(h);
19340 	} else {
19341 		return def_value;
19342 	}
19343 }
19344 
duk_get_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19345 DUK_INTERNAL const char *duk_get_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19346 	duk_hstring *h;
19347 
19348 	DUK_ASSERT_API_ENTRY(thr);
19349 
19350 	h = duk_get_hstring_notsymbol(thr, idx);
19351 	if (h) {
19352 		return (const char *) DUK_HSTRING_GET_DATA(h);
19353 	} else {
19354 		return NULL;
19355 	}
19356 }
19357 
duk_require_string(duk_hthread * thr,duk_idx_t idx)19358 DUK_EXTERNAL const char *duk_require_string(duk_hthread *thr, duk_idx_t idx) {
19359 	DUK_ASSERT_API_ENTRY(thr);
19360 
19361 	return duk_require_lstring(thr, idx, NULL);
19362 }
19363 
duk_require_string_notsymbol(duk_hthread * thr,duk_idx_t idx)19364 DUK_INTERNAL const char *duk_require_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19365 	duk_hstring *h;
19366 
19367 	DUK_ASSERT_API_ENTRY(thr);
19368 
19369 	h = duk_require_hstring_notsymbol(thr, idx);
19370 	DUK_ASSERT(h != NULL);
19371 	return (const char *) DUK_HSTRING_GET_DATA(h);
19372 }
19373 
duk_require_object(duk_hthread * thr,duk_idx_t idx)19374 DUK_EXTERNAL void duk_require_object(duk_hthread *thr, duk_idx_t idx) {
19375 	duk_tval *tv;
19376 
19377 	DUK_ASSERT_API_ENTRY(thr);
19378 
19379 	tv = duk_get_tval_or_unused(thr, idx);
19380 	DUK_ASSERT(tv != NULL);
19381 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19382 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19383 		DUK_WO_NORETURN(return;);
19384 	}
19385 }
19386 
duk__get_pointer_raw(duk_hthread * thr,duk_idx_t idx,void * def_value)19387 DUK_LOCAL void *duk__get_pointer_raw(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19388 	duk_tval *tv;
19389 	void *p;
19390 
19391 	DUK_ASSERT_CTX_VALID(thr);
19392 
19393 	tv = duk_get_tval_or_unused(thr, idx);
19394 	DUK_ASSERT(tv != NULL);
19395 	if (!DUK_TVAL_IS_POINTER(tv)) {
19396 		return def_value;
19397 	}
19398 
19399 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19400 	return p;
19401 }
19402 
duk_get_pointer(duk_hthread * thr,duk_idx_t idx)19403 DUK_EXTERNAL void *duk_get_pointer(duk_hthread *thr, duk_idx_t idx) {
19404 	DUK_ASSERT_API_ENTRY(thr);
19405 	return duk__get_pointer_raw(thr, idx, NULL /*def_value*/);
19406 }
19407 
duk_opt_pointer(duk_hthread * thr,duk_idx_t idx,void * def_value)19408 DUK_EXTERNAL void *duk_opt_pointer(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19409 	DUK_ASSERT_API_ENTRY(thr);
19410 
19411 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19412 		return def_value;
19413 	}
19414 	return duk_require_pointer(thr, idx);
19415 }
19416 
duk_get_pointer_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19417 DUK_EXTERNAL void *duk_get_pointer_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19418 	DUK_ASSERT_API_ENTRY(thr);
19419 	return duk__get_pointer_raw(thr, idx, def_value);
19420 }
19421 
duk_require_pointer(duk_hthread * thr,duk_idx_t idx)19422 DUK_EXTERNAL void *duk_require_pointer(duk_hthread *thr, duk_idx_t idx) {
19423 	duk_tval *tv;
19424 	void *p;
19425 
19426 	DUK_ASSERT_API_ENTRY(thr);
19427 
19428 	/* Note: here we must be wary of the fact that a pointer may be
19429 	 * valid and be a NULL.
19430 	 */
19431 	tv = duk_get_tval_or_unused(thr, idx);
19432 	DUK_ASSERT(tv != NULL);
19433 	if (DUK_UNLIKELY(!DUK_TVAL_IS_POINTER(tv))) {
19434 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "pointer", DUK_STR_NOT_POINTER);
19435 		DUK_WO_NORETURN(return NULL;);
19436 	}
19437 	p = DUK_TVAL_GET_POINTER(tv);  /* may be NULL */
19438 	return p;
19439 }
19440 
19441 #if 0  /*unused*/
19442 DUK_INTERNAL void *duk_get_voidptr(duk_hthread *thr, duk_idx_t idx) {
19443 	duk_tval *tv;
19444 	duk_heaphdr *h;
19445 
19446 	DUK_ASSERT_API_ENTRY(thr);
19447 
19448 	tv = duk_get_tval_or_unused(thr, idx);
19449 	DUK_ASSERT(tv != NULL);
19450 	if (!DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
19451 		return NULL;
19452 	}
19453 
19454 	h = DUK_TVAL_GET_HEAPHDR(tv);
19455 	DUK_ASSERT(h != NULL);
19456 	return (void *) h;
19457 }
19458 #endif
19459 
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)19460 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) {
19461 	duk_hbuffer *h;
19462 	void *ret;
19463 	duk_size_t len;
19464 	duk_tval *tv;
19465 
19466 	DUK_ASSERT_CTX_VALID(thr);
19467 
19468 	if (out_size != NULL) {
19469 		*out_size = 0;
19470 	}
19471 
19472 	tv = duk_get_tval_or_unused(thr, idx);
19473 	DUK_ASSERT(tv != NULL);
19474 	if (DUK_LIKELY(DUK_TVAL_IS_BUFFER(tv))) {
19475 		h = DUK_TVAL_GET_BUFFER(tv);
19476 		DUK_ASSERT(h != NULL);
19477 
19478 		len = DUK_HBUFFER_GET_SIZE(h);
19479 		ret = DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
19480 	} else {
19481 		if (throw_flag) {
19482 			DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19483 			DUK_WO_NORETURN(return NULL;);
19484 		}
19485 		len = def_size;
19486 		ret = def_ptr;
19487 	}
19488 
19489 	if (out_size != NULL) {
19490 		*out_size = len;
19491 	}
19492 	return ret;
19493 }
19494 
duk_get_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19495 DUK_EXTERNAL void *duk_get_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19496 	DUK_ASSERT_API_ENTRY(thr);
19497 
19498 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/);
19499 }
19500 
duk_opt_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19501 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) {
19502 	DUK_ASSERT_API_ENTRY(thr);
19503 
19504 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19505 		if (out_size != NULL) {
19506 			*out_size = def_size;
19507 		}
19508 		return def_ptr;
19509 	}
19510 	return duk_require_buffer(thr, idx, out_size);
19511 }
19512 
duk_get_buffer_default(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_len)19513 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) {
19514 	DUK_ASSERT_API_ENTRY(thr);
19515 
19516 	return duk__get_buffer_helper(thr, idx, out_size, def_ptr, def_len, 0 /*throw_flag*/);
19517 }
19518 
duk_require_buffer(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19519 DUK_EXTERNAL void *duk_require_buffer(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19520 	DUK_ASSERT_API_ENTRY(thr);
19521 
19522 	return duk__get_buffer_helper(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/);
19523 }
19524 
19525 /* Get the active buffer data area for a plain buffer or a buffer object.
19526  * Return NULL if the the value is not a buffer.  Note that a buffer may
19527  * have a NULL data pointer when its size is zero, the optional 'out_isbuffer'
19528  * argument allows caller to detect this reliably.
19529  */
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)19530 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) {
19531 	duk_tval *tv;
19532 
19533 	DUK_ASSERT_API_ENTRY(thr);
19534 
19535 	if (out_isbuffer != NULL) {
19536 		*out_isbuffer = 0;
19537 	}
19538 	if (out_size != NULL) {
19539 		*out_size = def_size;
19540 	}
19541 
19542 	tv = duk_get_tval_or_unused(thr, idx);
19543 	DUK_ASSERT(tv != NULL);
19544 
19545 	if (DUK_TVAL_IS_BUFFER(tv)) {
19546 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
19547 		DUK_ASSERT(h != NULL);
19548 		if (out_size != NULL) {
19549 			*out_size = DUK_HBUFFER_GET_SIZE(h);
19550 		}
19551 		if (out_isbuffer != NULL) {
19552 			*out_isbuffer = 1;
19553 		}
19554 		return (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);  /* may be NULL (but only if size is 0) */
19555 	}
19556 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
19557 	else if (DUK_TVAL_IS_OBJECT(tv)) {
19558 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
19559 		DUK_ASSERT(h != NULL);
19560 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
19561 			/* XXX: this is probably a useful shared helper: for a
19562 			 * duk_hbufobj, get a validated buffer pointer/length.
19563 			 */
19564 			duk_hbufobj *h_bufobj = (duk_hbufobj *) h;
19565 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
19566 
19567 			if (h_bufobj->buf != NULL &&
19568 			    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
19569 				duk_uint8_t *p;
19570 
19571 				p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf);
19572 				if (out_size != NULL) {
19573 					*out_size = (duk_size_t) h_bufobj->length;
19574 				}
19575 				if (out_isbuffer != NULL) {
19576 					*out_isbuffer = 1;
19577 				}
19578 				return (void *) (p + h_bufobj->offset);
19579 			}
19580 			/* if slice not fully valid, treat as error */
19581 		}
19582 	}
19583 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
19584 
19585 	if (throw_flag) {
19586 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19587 		DUK_WO_NORETURN(return NULL;);
19588 	}
19589 	return def_ptr;
19590 }
19591 
duk_get_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19592 DUK_EXTERNAL void *duk_get_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19593 	DUK_ASSERT_API_ENTRY(thr);
19594 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 0 /*throw_flag*/, NULL);
19595 }
19596 
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)19597 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) {
19598 	DUK_ASSERT_API_ENTRY(thr);
19599 	return duk_get_buffer_data_raw(thr, idx, out_size, def_ptr, def_size, 0 /*throw_flag*/, NULL);
19600 }
19601 
duk_opt_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,void * def_ptr,duk_size_t def_size)19602 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) {
19603 	DUK_ASSERT_API_ENTRY(thr);
19604 
19605 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19606 		if (out_size != NULL) {
19607 			*out_size = def_size;
19608 		}
19609 		return def_ptr;
19610 	}
19611 	return duk_require_buffer_data(thr, idx, out_size);
19612 }
19613 
duk_require_buffer_data(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size)19614 DUK_EXTERNAL void *duk_require_buffer_data(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size) {
19615 	DUK_ASSERT_API_ENTRY(thr);
19616 	return duk_get_buffer_data_raw(thr, idx, out_size, NULL /*def_ptr*/, 0 /*def_size*/, 1 /*throw_flag*/, NULL);
19617 }
19618 
19619 /* Raw helper for getting a value from the stack, checking its tag.
19620  * The tag cannot be a number because numbers don't have an internal
19621  * tag in the packed representation.
19622  */
19623 
duk__get_tagged_heaphdr_raw(duk_hthread * thr,duk_idx_t idx,duk_uint_t tag)19624 DUK_LOCAL duk_heaphdr *duk__get_tagged_heaphdr_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t tag) {
19625 	duk_tval *tv;
19626 	duk_heaphdr *ret;
19627 
19628 	DUK_ASSERT_CTX_VALID(thr);
19629 
19630 	tv = duk_get_tval_or_unused(thr, idx);
19631 	DUK_ASSERT(tv != NULL);
19632 	if (DUK_TVAL_GET_TAG(tv) != tag) {
19633 		return (duk_heaphdr *) NULL;
19634 	}
19635 
19636 	ret = DUK_TVAL_GET_HEAPHDR(tv);
19637 	DUK_ASSERT(ret != NULL);  /* tagged null pointers should never occur */
19638 	return ret;
19639 
19640 }
19641 
duk_get_hstring(duk_hthread * thr,duk_idx_t idx)19642 DUK_INTERNAL duk_hstring *duk_get_hstring(duk_hthread *thr, duk_idx_t idx) {
19643 	DUK_ASSERT_API_ENTRY(thr);
19644 	return (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19645 }
19646 
duk_get_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19647 DUK_INTERNAL duk_hstring *duk_get_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19648 	duk_hstring *h;
19649 
19650 	DUK_ASSERT_API_ENTRY(thr);
19651 
19652 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19653 	if (DUK_UNLIKELY(h && DUK_HSTRING_HAS_SYMBOL(h))) {
19654 		return NULL;
19655 	}
19656 	return h;
19657 }
19658 
duk_require_hstring(duk_hthread * thr,duk_idx_t idx)19659 DUK_INTERNAL duk_hstring *duk_require_hstring(duk_hthread *thr, duk_idx_t idx) {
19660 	duk_hstring *h;
19661 
19662 	DUK_ASSERT_API_ENTRY(thr);
19663 
19664 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19665 	if (DUK_UNLIKELY(h == NULL)) {
19666 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19667 		DUK_WO_NORETURN(return NULL;);
19668 	}
19669 	return h;
19670 }
19671 
duk_require_hstring_notsymbol(duk_hthread * thr,duk_idx_t idx)19672 DUK_INTERNAL duk_hstring *duk_require_hstring_notsymbol(duk_hthread *thr, duk_idx_t idx) {
19673 	duk_hstring *h;
19674 
19675 	DUK_ASSERT_API_ENTRY(thr);
19676 
19677 	h = (duk_hstring *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_STRING);
19678 	if (DUK_UNLIKELY(h == NULL || DUK_HSTRING_HAS_SYMBOL(h))) {
19679 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "string", DUK_STR_NOT_STRING);
19680 		DUK_WO_NORETURN(return NULL;);
19681 	}
19682 	return h;
19683 }
19684 
duk_get_hobject(duk_hthread * thr,duk_idx_t idx)19685 DUK_INTERNAL duk_hobject *duk_get_hobject(duk_hthread *thr, duk_idx_t idx) {
19686 	DUK_ASSERT_API_ENTRY(thr);
19687 	return (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19688 }
19689 
duk_require_hobject(duk_hthread * thr,duk_idx_t idx)19690 DUK_INTERNAL duk_hobject *duk_require_hobject(duk_hthread *thr, duk_idx_t idx) {
19691 	duk_hobject *h;
19692 
19693 	DUK_ASSERT_API_ENTRY(thr);
19694 
19695 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19696 	if (DUK_UNLIKELY(h == NULL)) {
19697 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19698 		DUK_WO_NORETURN(return NULL;);
19699 	}
19700 	return h;
19701 }
19702 
duk_get_hbuffer(duk_hthread * thr,duk_idx_t idx)19703 DUK_INTERNAL duk_hbuffer *duk_get_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19704 	DUK_ASSERT_API_ENTRY(thr);
19705 	return (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19706 }
19707 
duk_require_hbuffer(duk_hthread * thr,duk_idx_t idx)19708 DUK_INTERNAL duk_hbuffer *duk_require_hbuffer(duk_hthread *thr, duk_idx_t idx) {
19709 	duk_hbuffer *h;
19710 
19711 	DUK_ASSERT_API_ENTRY(thr);
19712 
19713 	h = (duk_hbuffer *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_BUFFER);
19714 	if (DUK_UNLIKELY(h == NULL)) {
19715 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "buffer", DUK_STR_NOT_BUFFER);
19716 		DUK_WO_NORETURN(return NULL;);
19717 	}
19718 	return h;
19719 }
19720 
duk_get_hthread(duk_hthread * thr,duk_idx_t idx)19721 DUK_INTERNAL duk_hthread *duk_get_hthread(duk_hthread *thr, duk_idx_t idx) {
19722 	duk_hobject *h;
19723 
19724 	DUK_ASSERT_API_ENTRY(thr);
19725 
19726 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19727 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_THREAD(h))) {
19728 		h = NULL;
19729 	}
19730 	return (duk_hthread *) h;
19731 }
19732 
duk_require_hthread(duk_hthread * thr,duk_idx_t idx)19733 DUK_INTERNAL duk_hthread *duk_require_hthread(duk_hthread *thr, duk_idx_t idx) {
19734 	duk_hobject *h;
19735 
19736 	DUK_ASSERT_API_ENTRY(thr);
19737 
19738 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19739 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_THREAD(h)))) {
19740 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "thread", DUK_STR_NOT_THREAD);
19741 		DUK_WO_NORETURN(return NULL;);
19742 	}
19743 	return (duk_hthread *) h;
19744 }
19745 
duk_get_hcompfunc(duk_hthread * thr,duk_idx_t idx)19746 DUK_INTERNAL duk_hcompfunc *duk_get_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19747 	duk_hobject *h;
19748 
19749 	DUK_ASSERT_API_ENTRY(thr);
19750 
19751 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19752 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_COMPFUNC(h))) {
19753 		h = NULL;
19754 	}
19755 	return (duk_hcompfunc *) h;
19756 }
19757 
duk_require_hcompfunc(duk_hthread * thr,duk_idx_t idx)19758 DUK_INTERNAL duk_hcompfunc *duk_require_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
19759 	duk_hobject *h;
19760 
19761 	DUK_ASSERT_API_ENTRY(thr);
19762 
19763 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19764 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_COMPFUNC(h)))) {
19765 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "compiledfunction", DUK_STR_NOT_COMPFUNC);
19766 		DUK_WO_NORETURN(return NULL;);
19767 	}
19768 	return (duk_hcompfunc *) h;
19769 }
19770 
duk_get_hnatfunc(duk_hthread * thr,duk_idx_t idx)19771 DUK_INTERNAL duk_hnatfunc *duk_get_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19772 	duk_hobject *h;
19773 
19774 	DUK_ASSERT_API_ENTRY(thr);
19775 
19776 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19777 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_IS_NATFUNC(h))) {
19778 		h = NULL;
19779 	}
19780 	return (duk_hnatfunc *) h;
19781 }
19782 
duk_require_hnatfunc(duk_hthread * thr,duk_idx_t idx)19783 DUK_INTERNAL duk_hnatfunc *duk_require_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
19784 	duk_hobject *h;
19785 
19786 	DUK_ASSERT_API_ENTRY(thr);
19787 
19788 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
19789 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_IS_NATFUNC(h)))) {
19790 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19791 		DUK_WO_NORETURN(return NULL;);
19792 	}
19793 	return (duk_hnatfunc *) h;
19794 }
19795 
duk_get_c_function(duk_hthread * thr,duk_idx_t idx)19796 DUK_EXTERNAL duk_c_function duk_get_c_function(duk_hthread *thr, duk_idx_t idx) {
19797 	duk_tval *tv;
19798 	duk_hobject *h;
19799 	duk_hnatfunc *f;
19800 
19801 	DUK_ASSERT_API_ENTRY(thr);
19802 
19803 	tv = duk_get_tval_or_unused(thr, idx);
19804 	DUK_ASSERT(tv != NULL);
19805 	if (DUK_UNLIKELY(!DUK_TVAL_IS_OBJECT(tv))) {
19806 		return NULL;
19807 	}
19808 	h = DUK_TVAL_GET_OBJECT(tv);
19809 	DUK_ASSERT(h != NULL);
19810 
19811 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_NATFUNC(h))) {
19812 		return NULL;
19813 	}
19814 	DUK_ASSERT(DUK_HOBJECT_HAS_NATFUNC(h));
19815 	f = (duk_hnatfunc *) h;
19816 
19817 	return f->func;
19818 }
19819 
duk_opt_c_function(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19820 DUK_EXTERNAL duk_c_function duk_opt_c_function(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19821 	DUK_ASSERT_API_ENTRY(thr);
19822 
19823 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19824 		return def_value;
19825 	}
19826 	return duk_require_c_function(thr, idx);
19827 }
19828 
duk_get_c_function_default(duk_hthread * thr,duk_idx_t idx,duk_c_function def_value)19829 DUK_EXTERNAL duk_c_function duk_get_c_function_default(duk_hthread *thr, duk_idx_t idx, duk_c_function def_value) {
19830 	duk_c_function ret;
19831 
19832 	DUK_ASSERT_API_ENTRY(thr);
19833 
19834 	ret = duk_get_c_function(thr, idx);
19835 	if (ret != NULL) {
19836 		return ret;
19837 	}
19838 
19839 	return def_value;
19840 }
19841 
duk_require_c_function(duk_hthread * thr,duk_idx_t idx)19842 DUK_EXTERNAL duk_c_function duk_require_c_function(duk_hthread *thr, duk_idx_t idx) {
19843 	duk_c_function ret;
19844 
19845 	DUK_ASSERT_API_ENTRY(thr);
19846 
19847 	ret = duk_get_c_function(thr, idx);
19848 	if (DUK_UNLIKELY(!ret)) {
19849 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "nativefunction", DUK_STR_NOT_NATFUNC);
19850 		DUK_WO_NORETURN(return ret;);
19851 	}
19852 	return ret;
19853 }
19854 
duk_require_function(duk_hthread * thr,duk_idx_t idx)19855 DUK_EXTERNAL void duk_require_function(duk_hthread *thr, duk_idx_t idx) {
19856 	DUK_ASSERT_API_ENTRY(thr);
19857 	if (DUK_UNLIKELY(!duk_is_function(thr, idx))) {
19858 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "function", DUK_STR_NOT_FUNCTION);
19859 		DUK_WO_NORETURN(return;);
19860 	}
19861 }
19862 
duk_require_constructable(duk_hthread * thr,duk_idx_t idx)19863 DUK_INTERNAL void duk_require_constructable(duk_hthread *thr, duk_idx_t idx) {
19864 	duk_hobject *h;
19865 
19866 	DUK_ASSERT_API_ENTRY(thr);
19867 
19868 	h = duk_require_hobject_accept_mask(thr, idx, DUK_TYPE_MASK_LIGHTFUNC);
19869 	if (DUK_UNLIKELY(h != NULL && !DUK_HOBJECT_HAS_CONSTRUCTABLE(h))) {
19870 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "constructable", DUK_STR_NOT_CONSTRUCTABLE);
19871 		DUK_WO_NORETURN(return;);
19872 	}
19873 	/* Lightfuncs (h == NULL) are constructable. */
19874 }
19875 
duk_get_context(duk_hthread * thr,duk_idx_t idx)19876 DUK_EXTERNAL duk_hthread *duk_get_context(duk_hthread *thr, duk_idx_t idx) {
19877 	DUK_ASSERT_API_ENTRY(thr);
19878 
19879 	return duk_get_hthread(thr, idx);
19880 }
19881 
duk_require_context(duk_hthread * thr,duk_idx_t idx)19882 DUK_EXTERNAL duk_hthread *duk_require_context(duk_hthread *thr, duk_idx_t idx) {
19883 	DUK_ASSERT_API_ENTRY(thr);
19884 
19885 	return duk_require_hthread(thr, idx);
19886 }
19887 
duk_opt_context(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19888 DUK_EXTERNAL duk_hthread *duk_opt_context(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19889 	DUK_ASSERT_API_ENTRY(thr);
19890 
19891 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19892 		return def_value;
19893 	}
19894 	return duk_require_context(thr, idx);
19895 }
19896 
duk_get_context_default(duk_hthread * thr,duk_idx_t idx,duk_hthread * def_value)19897 DUK_EXTERNAL duk_hthread *duk_get_context_default(duk_hthread *thr, duk_idx_t idx, duk_hthread *def_value) {
19898 	duk_hthread *ret;
19899 
19900 	DUK_ASSERT_API_ENTRY(thr);
19901 
19902 	ret = duk_get_context(thr, idx);
19903 	if (ret != NULL) {
19904 		return ret;
19905 	}
19906 
19907 	return def_value;
19908 }
19909 
duk_get_heapptr(duk_hthread * thr,duk_idx_t idx)19910 DUK_EXTERNAL void *duk_get_heapptr(duk_hthread *thr, duk_idx_t idx) {
19911 	duk_tval *tv;
19912 	void *ret;
19913 
19914 	DUK_ASSERT_API_ENTRY(thr);
19915 
19916 	tv = duk_get_tval_or_unused(thr, idx);
19917 	DUK_ASSERT(tv != NULL);
19918 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
19919 		return (void *) NULL;
19920 	}
19921 
19922 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
19923 	DUK_ASSERT(ret != NULL);
19924 	return ret;
19925 }
19926 
duk_opt_heapptr(duk_hthread * thr,duk_idx_t idx,void * def_value)19927 DUK_EXTERNAL void *duk_opt_heapptr(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19928 	DUK_ASSERT_API_ENTRY(thr);
19929 
19930 	if (duk_check_type_mask(thr, idx, DUK_TYPE_MASK_NONE | DUK_TYPE_MASK_UNDEFINED)) {
19931 		return def_value;
19932 	}
19933 	return duk_require_heapptr(thr, idx);
19934 }
19935 
duk_get_heapptr_default(duk_hthread * thr,duk_idx_t idx,void * def_value)19936 DUK_EXTERNAL void *duk_get_heapptr_default(duk_hthread *thr, duk_idx_t idx, void *def_value) {
19937 	void *ret;
19938 
19939 	DUK_ASSERT_API_ENTRY(thr);
19940 
19941 	ret = duk_get_heapptr(thr, idx);
19942 	if (ret != NULL) {
19943 		return ret;
19944 	}
19945 
19946 	return def_value;
19947 }
19948 
duk_require_heapptr(duk_hthread * thr,duk_idx_t idx)19949 DUK_EXTERNAL void *duk_require_heapptr(duk_hthread *thr, duk_idx_t idx) {
19950 	duk_tval *tv;
19951 	void *ret;
19952 
19953 	DUK_ASSERT_API_ENTRY(thr);
19954 
19955 	tv = duk_get_tval_or_unused(thr, idx);
19956 	DUK_ASSERT(tv != NULL);
19957 	if (DUK_UNLIKELY(!DUK_TVAL_IS_HEAP_ALLOCATED(tv))) {
19958 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "heapobject", DUK_STR_UNEXPECTED_TYPE);
19959 		DUK_WO_NORETURN(return NULL;);
19960 	}
19961 
19962 	ret = (void *) DUK_TVAL_GET_HEAPHDR(tv);
19963 	DUK_ASSERT(ret != NULL);
19964 	return ret;
19965 }
19966 
19967 /* 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)19968 DUK_LOCAL duk_hobject *duk__get_hobject_promote_mask_raw(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
19969 	duk_uint_t val_mask;
19970 	duk_hobject *res;
19971 
19972 	DUK_ASSERT_CTX_VALID(thr);
19973 
19974 	res = duk_get_hobject(thr, idx);  /* common case, not promoted */
19975 	if (DUK_LIKELY(res != NULL)) {
19976 		DUK_ASSERT(res != NULL);
19977 		return res;
19978 	}
19979 
19980 	val_mask = duk_get_type_mask(thr, idx);
19981 	if (val_mask & type_mask) {
19982 		if (type_mask & DUK_TYPE_MASK_PROMOTE) {
19983 			res = duk_to_hobject(thr, idx);
19984 			DUK_ASSERT(res != NULL);
19985 			return res;
19986 		} else {
19987 			return NULL;  /* accept without promoting */
19988 		}
19989 	}
19990 
19991 	if (type_mask & DUK_TYPE_MASK_THROW) {
19992 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, "object", DUK_STR_NOT_OBJECT);
19993 		DUK_WO_NORETURN(return NULL;);
19994 	}
19995 	return NULL;
19996 }
19997 
19998 /* Get a duk_hobject * at 'idx'; if the value is not an object but matches the
19999  * supplied 'type_mask', promote it to an object and return the duk_hobject *.
20000  * This is useful for call sites which want an object but also accept a plain
20001  * buffer and/or a lightfunc which gets automatically promoted to an object.
20002  * Return value is NULL if value is neither an object nor a plain type allowed
20003  * by the mask.
20004  */
duk_get_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20005 DUK_INTERNAL duk_hobject *duk_get_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20006 	DUK_ASSERT_API_ENTRY(thr);
20007 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_PROMOTE);
20008 }
20009 
20010 /* Like duk_get_hobject_promote_mask() but throw a TypeError instead of
20011  * returning a NULL.
20012  */
duk_require_hobject_promote_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20013 DUK_INTERNAL duk_hobject *duk_require_hobject_promote_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20014 	DUK_ASSERT_API_ENTRY(thr);
20015 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW | DUK_TYPE_MASK_PROMOTE);
20016 }
20017 
20018 /* Require a duk_hobject * at 'idx'; if the value is not an object but matches the
20019  * supplied 'type_mask', return a NULL instead.  Otherwise throw a TypeError.
20020  */
duk_require_hobject_accept_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t type_mask)20021 DUK_INTERNAL duk_hobject *duk_require_hobject_accept_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t type_mask) {
20022 	DUK_ASSERT_API_ENTRY(thr);
20023 	return duk__get_hobject_promote_mask_raw(thr, idx, type_mask | DUK_TYPE_MASK_THROW);
20024 }
20025 
duk_get_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20026 DUK_INTERNAL duk_hobject *duk_get_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20027 	duk_hobject *h;
20028 
20029 	DUK_ASSERT_API_ENTRY(thr);
20030 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20031 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20032 
20033 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20034 	if (DUK_UNLIKELY(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) != classnum)) {
20035 		h = NULL;
20036 	}
20037 	return h;
20038 }
20039 
duk_require_hobject_with_class(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t classnum)20040 DUK_INTERNAL duk_hobject *duk_require_hobject_with_class(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t classnum) {
20041 	duk_hobject *h;
20042 
20043 	DUK_ASSERT_API_ENTRY(thr);
20044 	DUK_ASSERT_DISABLE(classnum >= 0);  /* unsigned */
20045 	DUK_ASSERT(classnum <= DUK_HOBJECT_CLASS_MAX);
20046 
20047 	h = (duk_hobject *) duk__get_tagged_heaphdr_raw(thr, idx, DUK_TAG_OBJECT);
20048 	if (DUK_UNLIKELY(!(h != NULL && DUK_HOBJECT_GET_CLASS_NUMBER(h) == classnum))) {
20049 		duk_hstring *h_class;
20050 		h_class = DUK_HTHREAD_GET_STRING(thr, DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum));
20051 		DUK_UNREF(h_class);
20052 
20053 		DUK_ERROR_REQUIRE_TYPE_INDEX(thr, idx, (const char *) DUK_HSTRING_GET_DATA(h_class), DUK_STR_UNEXPECTED_TYPE);
20054 		DUK_WO_NORETURN(return NULL;);
20055 	}
20056 	return h;
20057 }
20058 
duk_get_length(duk_hthread * thr,duk_idx_t idx)20059 DUK_EXTERNAL duk_size_t duk_get_length(duk_hthread *thr, duk_idx_t idx) {
20060 	duk_tval *tv;
20061 
20062 	DUK_ASSERT_API_ENTRY(thr);
20063 
20064 	tv = duk_get_tval_or_unused(thr, idx);
20065 	DUK_ASSERT(tv != NULL);
20066 
20067 	switch (DUK_TVAL_GET_TAG(tv)) {
20068 	case DUK_TAG_UNDEFINED:
20069 	case DUK_TAG_NULL:
20070 	case DUK_TAG_BOOLEAN:
20071 	case DUK_TAG_POINTER:
20072 		return 0;
20073 #if defined(DUK_USE_PREFER_SIZE)
20074 	/* String and buffer have a virtual non-configurable .length property
20075 	 * which is within size_t range so it can be looked up without specific
20076 	 * type checks.  Lightfuncs inherit from %NativeFunctionPrototype%
20077 	 * which provides an inherited .length accessor; it could be overwritten
20078 	 * to produce unexpected types or values, but just number convert and
20079 	 * duk_size_t cast for now.
20080 	 */
20081 	case DUK_TAG_STRING:
20082 	case DUK_TAG_BUFFER:
20083 	case DUK_TAG_LIGHTFUNC: {
20084 		duk_size_t ret;
20085 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20086 		ret = (duk_size_t) duk_to_number_m1(thr);
20087 		duk_pop_unsafe(thr);
20088 		return ret;
20089 	}
20090 #else  /* DUK_USE_PREFER_SIZE */
20091 	case DUK_TAG_STRING: {
20092 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
20093 		DUK_ASSERT(h != NULL);
20094 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20095 			return 0;
20096 		}
20097 		return (duk_size_t) DUK_HSTRING_GET_CHARLEN(h);
20098 	}
20099 	case DUK_TAG_BUFFER: {
20100 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
20101 		DUK_ASSERT(h != NULL);
20102 		return (duk_size_t) DUK_HBUFFER_GET_SIZE(h);
20103 	}
20104 	case DUK_TAG_LIGHTFUNC: {
20105 		/* We could look up the length from the lightfunc duk_tval,
20106 		 * but since Duktape 2.2 lightfunc .length comes from
20107 		 * %NativeFunctionPrototype% which can be overridden, so
20108 		 * look up the property explicitly.
20109 		 */
20110 		duk_size_t ret;
20111 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20112 		ret = (duk_size_t) duk_to_number_m1(thr);
20113 		duk_pop_unsafe(thr);
20114 		return ret;
20115 	}
20116 #endif  /* DUK_USE_PREFER_SIZE */
20117 	case DUK_TAG_OBJECT: {
20118 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
20119 		DUK_ASSERT(h != NULL);
20120 		return (duk_size_t) duk_hobject_get_length(thr, h);
20121 	}
20122 #if defined(DUK_USE_FASTINT)
20123 	case DUK_TAG_FASTINT:
20124 #endif
20125 	default:
20126 		/* number or 'unused' */
20127 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv) || DUK_TVAL_IS_UNUSED(tv));
20128 		return 0;
20129 	}
20130 
20131 	DUK_UNREACHABLE();
20132 }
20133 
20134 /*
20135  *  duk_known_xxx() helpers
20136  *
20137  *  Used internally when we're 100% sure that a certain index is valid and
20138  *  contains an object of a certain type.  For example, if we duk_push_object()
20139  *  we can then safely duk_known_hobject(thr, -1).  These helpers just assert
20140  *  for the index and type, and if the assumptions are not valid, memory unsafe
20141  *  behavior happens.
20142  */
20143 
duk__known_heaphdr(duk_hthread * thr,duk_idx_t idx)20144 DUK_LOCAL duk_heaphdr *duk__known_heaphdr(duk_hthread *thr, duk_idx_t idx) {
20145 	duk_tval *tv;
20146 	duk_heaphdr *h;
20147 
20148 	DUK_ASSERT_CTX_VALID(thr);
20149 	if (idx < 0) {
20150 		tv = thr->valstack_top + idx;
20151 	} else {
20152 		tv = thr->valstack_bottom + idx;
20153 	}
20154 	DUK_ASSERT(tv >= thr->valstack_bottom);
20155 	DUK_ASSERT(tv < thr->valstack_top);
20156 	h = DUK_TVAL_GET_HEAPHDR(tv);
20157 	DUK_ASSERT(h != NULL);
20158 	return h;
20159 }
20160 
duk_known_hstring(duk_hthread * thr,duk_idx_t idx)20161 DUK_INTERNAL duk_hstring *duk_known_hstring(duk_hthread *thr, duk_idx_t idx) {
20162 	DUK_ASSERT_API_ENTRY(thr);
20163 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20164 	return (duk_hstring *) duk__known_heaphdr(thr, idx);
20165 }
20166 
duk_known_hobject(duk_hthread * thr,duk_idx_t idx)20167 DUK_INTERNAL duk_hobject *duk_known_hobject(duk_hthread *thr, duk_idx_t idx) {
20168 	DUK_ASSERT_API_ENTRY(thr);
20169 	DUK_ASSERT(duk_get_hobject(thr, idx) != NULL);
20170 	return (duk_hobject *) duk__known_heaphdr(thr, idx);
20171 }
20172 
duk_known_hbuffer(duk_hthread * thr,duk_idx_t idx)20173 DUK_INTERNAL duk_hbuffer *duk_known_hbuffer(duk_hthread *thr, duk_idx_t idx) {
20174 	DUK_ASSERT_API_ENTRY(thr);
20175 	DUK_ASSERT(duk_get_hbuffer(thr, idx) != NULL);
20176 	return (duk_hbuffer *) duk__known_heaphdr(thr, idx);
20177 }
20178 
duk_known_hcompfunc(duk_hthread * thr,duk_idx_t idx)20179 DUK_INTERNAL duk_hcompfunc *duk_known_hcompfunc(duk_hthread *thr, duk_idx_t idx) {
20180 	DUK_ASSERT_API_ENTRY(thr);
20181 	DUK_ASSERT(duk_get_hcompfunc(thr, idx) != NULL);
20182 	return (duk_hcompfunc *) duk__known_heaphdr(thr, idx);
20183 }
20184 
duk_known_hnatfunc(duk_hthread * thr,duk_idx_t idx)20185 DUK_INTERNAL duk_hnatfunc *duk_known_hnatfunc(duk_hthread *thr, duk_idx_t idx) {
20186 	DUK_ASSERT_API_ENTRY(thr);
20187 	DUK_ASSERT(duk_get_hnatfunc(thr, idx) != NULL);
20188 	return (duk_hnatfunc *) duk__known_heaphdr(thr, idx);
20189 }
20190 
duk_set_length(duk_hthread * thr,duk_idx_t idx,duk_size_t len)20191 DUK_EXTERNAL void duk_set_length(duk_hthread *thr, duk_idx_t idx, duk_size_t len) {
20192 	DUK_ASSERT_API_ENTRY(thr);
20193 
20194 	idx = duk_normalize_index(thr, idx);
20195 	duk_push_uint(thr, (duk_uint_t) len);
20196 	duk_put_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
20197 }
20198 
20199 /*
20200  *  Conversions and coercions
20201  *
20202  *  The conversion/coercions are in-place operations on the value stack.
20203  *  Some operations are implemented here directly, while others call a
20204  *  helper in duk_js_ops.c after validating arguments.
20205  */
20206 
20207 /* E5 Section 8.12.8 */
20208 
duk__defaultvalue_coerce_attempt(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t func_stridx)20209 DUK_LOCAL duk_bool_t duk__defaultvalue_coerce_attempt(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t func_stridx) {
20210 	if (duk_get_prop_stridx(thr, idx, func_stridx)) {
20211 		/* [ ... func ] */
20212 		if (duk_is_callable(thr, -1)) {
20213 			duk_dup(thr, idx);         /* -> [ ... func this ] */
20214 			duk_call_method(thr, 0);     /* -> [ ... retval ] */
20215 			if (duk_is_primitive(thr, -1)) {
20216 				duk_replace(thr, idx);
20217 				return 1;
20218 			}
20219 			/* [ ... retval ]; popped below */
20220 		}
20221 	}
20222 	duk_pop_unsafe(thr);  /* [ ... func/retval ] -> [ ... ] */
20223 	return 0;
20224 }
20225 
duk_to_undefined(duk_hthread * thr,duk_idx_t idx)20226 DUK_EXTERNAL void duk_to_undefined(duk_hthread *thr, duk_idx_t idx) {
20227 	duk_tval *tv;
20228 
20229 	DUK_ASSERT_API_ENTRY(thr);
20230 
20231 	tv = duk_require_tval(thr, idx);
20232 	DUK_ASSERT(tv != NULL);
20233 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
20234 }
20235 
duk_to_null(duk_hthread * thr,duk_idx_t idx)20236 DUK_EXTERNAL void duk_to_null(duk_hthread *thr, duk_idx_t idx) {
20237 	duk_tval *tv;
20238 
20239 	DUK_ASSERT_API_ENTRY(thr);
20240 
20241 	tv = duk_require_tval(thr, idx);
20242 	DUK_ASSERT(tv != NULL);
20243 	DUK_TVAL_SET_NULL_UPDREF(thr, tv);  /* side effects */
20244 }
20245 
20246 /* E5 Section 9.1 */
20247 DUK_LOCAL const char * const duk__toprim_hint_strings[3] = {
20248 	"default", "string", "number"
20249 };
duk__to_primitive_helper(duk_hthread * thr,duk_idx_t idx,duk_int_t hint,duk_bool_t check_symbol)20250 DUK_LOCAL void duk__to_primitive_helper(duk_hthread *thr, duk_idx_t idx, duk_int_t hint, duk_bool_t check_symbol) {
20251 	/* Inline initializer for coercers[] is not allowed by old compilers like BCC. */
20252 	duk_small_uint_t coercers[2];
20253 
20254 	DUK_ASSERT_API_ENTRY(thr);
20255 	DUK_ASSERT(hint == DUK_HINT_NONE || hint == DUK_HINT_NUMBER || hint == DUK_HINT_STRING);
20256 
20257 	idx = duk_require_normalize_index(thr, idx);
20258 
20259 	/* If already primitive, return as is. */
20260 	if (!duk_check_type_mask(thr, idx, DUK_TYPE_MASK_OBJECT |
20261 	                                   DUK_TYPE_MASK_LIGHTFUNC |
20262 	                                   DUK_TYPE_MASK_BUFFER)) {
20263 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20264 		return;
20265 	}
20266 
20267 	/* @@toPrimitive lookup.  Also do for plain buffers and lightfuncs
20268 	 * which mimic objects.
20269 	 */
20270 	if (check_symbol && duk_get_method_stridx(thr, idx, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_PRIMITIVE)) {
20271 		DUK_ASSERT(hint >= 0 && (duk_size_t) hint < sizeof(duk__toprim_hint_strings) / sizeof(const char *));
20272 		duk_dup(thr, idx);
20273 		duk_push_string(thr, duk__toprim_hint_strings[hint]);
20274 		duk_call_method(thr, 1);  /* [ ... method value hint ] -> [ ... res] */
20275 		if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
20276 	                                         DUK_TYPE_MASK_LIGHTFUNC |
20277 		                                 DUK_TYPE_MASK_BUFFER)) {
20278 			goto fail;
20279 		}
20280 		duk_replace(thr, idx);
20281 		return;
20282 	}
20283 
20284 	/* Objects are coerced based on E5 specification.
20285 	 * Lightfuncs are coerced because they behave like
20286 	 * objects even if they're internally a primitive
20287 	 * type.  Same applies to plain buffers, which behave
20288 	 * like ArrayBuffer objects since Duktape 2.x.
20289 	 */
20290 
20291 	/* Hint magic for Date is unnecessary in ES2015 because of
20292 	 * Date.prototype[@@toPrimitive].  However, it is needed if
20293 	 * symbol support is not enabled.
20294 	 */
20295 #if defined(DUK_USE_SYMBOL_BUILTIN)
20296 	if (hint == DUK_HINT_NONE) {
20297 		hint = DUK_HINT_NUMBER;
20298 	}
20299 #else  /* DUK_USE_SYMBOL_BUILTIN */
20300 	if (hint == DUK_HINT_NONE) {
20301 		duk_small_uint_t class_number;
20302 
20303 		class_number = duk_get_class_number(thr, idx);
20304 		if (class_number == DUK_HOBJECT_CLASS_DATE) {
20305 			hint = DUK_HINT_STRING;
20306 		} else {
20307 			hint = DUK_HINT_NUMBER;
20308 		}
20309 	}
20310 #endif  /* DUK_USE_SYMBOL_BUILTIN */
20311 
20312 	coercers[0] = DUK_STRIDX_VALUE_OF;
20313 	coercers[1] = DUK_STRIDX_TO_STRING;
20314 	if (hint == DUK_HINT_STRING) {
20315 		coercers[0] = DUK_STRIDX_TO_STRING;
20316 		coercers[1] = DUK_STRIDX_VALUE_OF;
20317 	}
20318 
20319 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[0])) {
20320 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20321 		return;
20322 	}
20323 
20324 	if (duk__defaultvalue_coerce_attempt(thr, idx, coercers[1])) {
20325 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* duk_to_string() relies on this behavior */
20326 		return;
20327 	}
20328 
20329  fail:
20330 	DUK_ERROR_TYPE(thr, DUK_STR_TOPRIMITIVE_FAILED);
20331 	DUK_WO_NORETURN(return;);
20332 }
20333 
duk_to_primitive(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20334 DUK_EXTERNAL void duk_to_primitive(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20335 	duk__to_primitive_helper(thr, idx, hint, 1 /*check_symbol*/);
20336 }
20337 
20338 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_to_primitive_ordinary(duk_hthread * thr,duk_idx_t idx,duk_int_t hint)20339 DUK_INTERNAL void duk_to_primitive_ordinary(duk_hthread *thr, duk_idx_t idx, duk_int_t hint) {
20340 	duk__to_primitive_helper(thr, idx, hint, 0 /*check_symbol*/);
20341 }
20342 #endif
20343 
20344 /* E5 Section 9.2 */
duk_to_boolean(duk_hthread * thr,duk_idx_t idx)20345 DUK_EXTERNAL duk_bool_t duk_to_boolean(duk_hthread *thr, duk_idx_t idx) {
20346 	duk_tval *tv;
20347 	duk_bool_t val;
20348 
20349 	DUK_ASSERT_API_ENTRY(thr);
20350 
20351 	idx = duk_require_normalize_index(thr, idx);
20352 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20353 	DUK_ASSERT(tv != NULL);
20354 
20355 	val = duk_js_toboolean(tv);
20356 	DUK_ASSERT(val == 0 || val == 1);
20357 
20358 	/* Note: no need to re-lookup tv, conversion is side effect free. */
20359 	DUK_ASSERT(tv != NULL);
20360 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, val);  /* side effects */
20361 	return val;
20362 }
20363 
duk_to_boolean_top_pop(duk_hthread * thr)20364 DUK_INTERNAL duk_bool_t duk_to_boolean_top_pop(duk_hthread *thr) {
20365 	duk_tval *tv;
20366 	duk_bool_t val;
20367 
20368 	DUK_ASSERT_API_ENTRY(thr);
20369 
20370 	tv = duk_require_tval(thr, -1);
20371 	DUK_ASSERT(tv != NULL);
20372 
20373 	val = duk_js_toboolean(tv);
20374 	DUK_ASSERT(val == 0 || val == 1);
20375 
20376 	duk_pop_unsafe(thr);
20377 	return val;
20378 }
20379 
duk_to_number(duk_hthread * thr,duk_idx_t idx)20380 DUK_EXTERNAL duk_double_t duk_to_number(duk_hthread *thr, duk_idx_t idx) {
20381 	duk_tval *tv;
20382 	duk_double_t d;
20383 
20384 	DUK_ASSERT_API_ENTRY(thr);
20385 
20386 	/* XXX: No need to normalize; the whole operation could be inlined here to
20387 	 * avoid 'tv' re-lookup.
20388 	 */
20389 	idx = duk_require_normalize_index(thr, idx);
20390 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20391 	DUK_ASSERT(tv != NULL);
20392 	d = duk_js_tonumber(thr, tv);  /* XXX: fastint coercion? now result will always be a non-fastint */
20393 
20394 	/* ToNumber() may have side effects so must relookup 'tv'. */
20395 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20396 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20397 	return d;
20398 }
20399 
duk_to_number_m1(duk_hthread * thr)20400 DUK_INTERNAL duk_double_t duk_to_number_m1(duk_hthread *thr) {
20401 	DUK_ASSERT_API_ENTRY(thr);
20402 	return duk_to_number(thr, -1);
20403 }
duk_to_number_m2(duk_hthread * thr)20404 DUK_INTERNAL duk_double_t duk_to_number_m2(duk_hthread *thr) {
20405 	DUK_ASSERT_API_ENTRY(thr);
20406 	return duk_to_number(thr, -2);
20407 }
20408 
duk_to_number_tval(duk_hthread * thr,duk_tval * tv)20409 DUK_INTERNAL duk_double_t duk_to_number_tval(duk_hthread *thr, duk_tval *tv) {
20410 #if defined(DUK_USE_PREFER_SIZE)
20411 	duk_double_t res;
20412 
20413 	DUK_ASSERT_API_ENTRY(thr);
20414 
20415 	duk_push_tval(thr, tv);
20416 	res = duk_to_number_m1(thr);
20417 	duk_pop_unsafe(thr);
20418 	return res;
20419 #else
20420 	duk_double_t res;
20421 	duk_tval *tv_dst;
20422 
20423 	DUK_ASSERT_API_ENTRY(thr);
20424 	DUK__ASSERT_SPACE();
20425 
20426 	tv_dst = thr->valstack_top++;
20427 	DUK_TVAL_SET_TVAL(tv_dst, tv);
20428 	DUK_TVAL_INCREF(thr, tv_dst);  /* decref not necessary */
20429 	res = duk_to_number_m1(thr);  /* invalidates tv_dst */
20430 
20431 	tv_dst = --thr->valstack_top;
20432 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_dst));
20433 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_dst));  /* plain number */
20434 	DUK_TVAL_SET_UNDEFINED(tv_dst);  /* valstack init policy */
20435 
20436 	return res;
20437 #endif
20438 }
20439 
20440 /* XXX: combine all the integer conversions: they share everything
20441  * but the helper function for coercion.
20442  */
20443 
20444 typedef duk_double_t (*duk__toint_coercer)(duk_hthread *thr, duk_tval *tv);
20445 
duk__to_int_uint_helper(duk_hthread * thr,duk_idx_t idx,duk__toint_coercer coerce_func)20446 DUK_LOCAL duk_double_t duk__to_int_uint_helper(duk_hthread *thr, duk_idx_t idx, duk__toint_coercer coerce_func) {
20447 	duk_tval *tv;
20448 	duk_double_t d;
20449 
20450 	DUK_ASSERT_CTX_VALID(thr);
20451 
20452 	tv = duk_require_tval(thr, idx);
20453 	DUK_ASSERT(tv != NULL);
20454 
20455 #if defined(DUK_USE_FASTINT)
20456 	/* If argument is a fastint, guarantee that it remains one.
20457 	 * There's no downgrade check for other cases.
20458 	 */
20459 	if (DUK_TVAL_IS_FASTINT(tv)) {
20460 		/* XXX: Unnecessary conversion back and forth. */
20461 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
20462 	}
20463 #endif
20464 	d = coerce_func(thr, tv);
20465 
20466 	/* XXX: fastint? */
20467 
20468 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20469 	tv = duk_require_tval(thr, idx);
20470 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, d);  /* side effects */
20471 	return d;
20472 }
20473 
duk_to_int(duk_hthread * thr,duk_idx_t idx)20474 DUK_EXTERNAL duk_int_t duk_to_int(duk_hthread *thr, duk_idx_t idx) {
20475 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20476 	 * API return value coercion: custom.
20477 	 */
20478 	DUK_ASSERT_API_ENTRY(thr);
20479 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20480 	return (duk_int_t) duk__api_coerce_d2i(thr, idx, 0 /*def_value*/, 0 /*require*/);
20481 }
20482 
duk_to_uint(duk_hthread * thr,duk_idx_t idx)20483 DUK_EXTERNAL duk_uint_t duk_to_uint(duk_hthread *thr, duk_idx_t idx) {
20484 	/* Value coercion (in stack): ToInteger(), E5 Section 9.4,
20485 	 * API return value coercion: custom.
20486 	 */
20487 	DUK_ASSERT_API_ENTRY(thr);
20488 	(void) duk__to_int_uint_helper(thr, idx, duk_js_tointeger);
20489 	return (duk_uint_t) duk__api_coerce_d2ui(thr, idx, 0 /*def_value*/, 0 /*require*/);
20490 }
20491 
duk_to_int32(duk_hthread * thr,duk_idx_t idx)20492 DUK_EXTERNAL duk_int32_t duk_to_int32(duk_hthread *thr, duk_idx_t idx) {
20493 	duk_tval *tv;
20494 	duk_int32_t ret;
20495 
20496 	DUK_ASSERT_API_ENTRY(thr);
20497 
20498 	tv = duk_require_tval(thr, idx);
20499 	DUK_ASSERT(tv != NULL);
20500 	ret = duk_js_toint32(thr, tv);
20501 
20502 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20503 	tv = duk_require_tval(thr, idx);
20504 	DUK_TVAL_SET_I32_UPDREF(thr, tv, ret);  /* side effects */
20505 	return ret;
20506 }
20507 
duk_to_uint32(duk_hthread * thr,duk_idx_t idx)20508 DUK_EXTERNAL duk_uint32_t duk_to_uint32(duk_hthread *thr, duk_idx_t idx) {
20509 	duk_tval *tv;
20510 	duk_uint32_t ret;
20511 
20512 	DUK_ASSERT_API_ENTRY(thr);
20513 
20514 	tv = duk_require_tval(thr, idx);
20515 	DUK_ASSERT(tv != NULL);
20516 	ret = duk_js_touint32(thr, tv);
20517 
20518 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20519 	tv = duk_require_tval(thr, idx);
20520 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20521 	return ret;
20522 }
20523 
duk_to_uint16(duk_hthread * thr,duk_idx_t idx)20524 DUK_EXTERNAL duk_uint16_t duk_to_uint16(duk_hthread *thr, duk_idx_t idx) {
20525 	duk_tval *tv;
20526 	duk_uint16_t ret;
20527 
20528 	DUK_ASSERT_API_ENTRY(thr);
20529 
20530 	tv = duk_require_tval(thr, idx);
20531 	DUK_ASSERT(tv != NULL);
20532 	ret = duk_js_touint16(thr, tv);
20533 
20534 	/* Relookup in case coerce_func() has side effects, e.g. ends up coercing an object */
20535 	tv = duk_require_tval(thr, idx);
20536 	DUK_TVAL_SET_U32_UPDREF(thr, tv, ret);  /* side effects */
20537 	return ret;
20538 }
20539 
20540 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
20541 /* Special coercion for Uint8ClampedArray. */
duk_to_uint8clamped(duk_hthread * thr,duk_idx_t idx)20542 DUK_INTERNAL duk_uint8_t duk_to_uint8clamped(duk_hthread *thr, duk_idx_t idx) {
20543 	duk_double_t d;
20544 	duk_double_t t;
20545 	duk_uint8_t ret;
20546 
20547 	DUK_ASSERT_API_ENTRY(thr);
20548 
20549 	/* XXX: Simplify this algorithm, should be possible to come up with
20550 	 * a shorter and faster algorithm by inspecting IEEE representation
20551 	 * directly.
20552 	 */
20553 
20554 	d = duk_to_number(thr, idx);
20555 	if (d <= 0.0) {
20556 		return 0;
20557 	} else if (d >= 255) {
20558 		return 255;
20559 	} else if (DUK_ISNAN(d)) {
20560 		/* Avoid NaN-to-integer coercion as it is compiler specific. */
20561 		return 0;
20562 	}
20563 
20564 	t = d - DUK_FLOOR(d);
20565 	if (t == 0.5) {
20566 		/* Exact halfway, round to even. */
20567 		ret = (duk_uint8_t) d;
20568 		ret = (ret + 1) & 0xfe;  /* Example: d=3.5, t=0.5 -> ret = (3 + 1) & 0xfe = 4 & 0xfe = 4
20569 		                          * Example: d=4.5, t=0.5 -> ret = (4 + 1) & 0xfe = 5 & 0xfe = 4
20570 		                          */
20571 	} else {
20572 		/* Not halfway, round to nearest. */
20573 		ret = (duk_uint8_t) (d + 0.5);
20574 	}
20575 	return ret;
20576 }
20577 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
20578 
duk_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20579 DUK_EXTERNAL const char *duk_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20580 	DUK_ASSERT_API_ENTRY(thr);
20581 
20582 	(void) duk_to_string(thr, idx);
20583 	DUK_ASSERT(duk_is_string(thr, idx));
20584 	return duk_require_lstring(thr, idx, out_len);
20585 }
20586 
duk__safe_to_string_raw(duk_hthread * thr,void * udata)20587 DUK_LOCAL duk_ret_t duk__safe_to_string_raw(duk_hthread *thr, void *udata) {
20588 	DUK_ASSERT_CTX_VALID(thr);
20589 	DUK_UNREF(udata);
20590 
20591 	duk_to_string(thr, -1);
20592 	return 1;
20593 }
20594 
duk_safe_to_lstring(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_len)20595 DUK_EXTERNAL const char *duk_safe_to_lstring(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_len) {
20596 	DUK_ASSERT_API_ENTRY(thr);
20597 
20598 	idx = duk_require_normalize_index(thr, idx);
20599 
20600 	/* We intentionally ignore the duk_safe_call() return value and only
20601 	 * check the output type.  This way we don't also need to check that
20602 	 * the returned value is indeed a string in the success case.
20603 	 */
20604 
20605 	duk_dup(thr, idx);
20606 	(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20607 	if (!duk_is_string(thr, -1)) {
20608 		/* Error: try coercing error to string once. */
20609 		(void) duk_safe_call(thr, duk__safe_to_string_raw, NULL /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
20610 		if (!duk_is_string(thr, -1)) {
20611 			/* Double error */
20612 			duk_pop_unsafe(thr);
20613 			duk_push_hstring_stridx(thr, DUK_STRIDX_UC_ERROR);
20614 		} else {
20615 			;
20616 		}
20617 	} else {
20618 		/* String; may be a symbol, accepted. */
20619 		;
20620 	}
20621 	DUK_ASSERT(duk_is_string(thr, -1));
20622 
20623 	duk_replace(thr, idx);
20624 	DUK_ASSERT(duk_get_string(thr, idx) != NULL);
20625 	return duk_get_lstring(thr, idx, out_len);
20626 }
20627 
duk_to_property_key_hstring(duk_hthread * thr,duk_idx_t idx)20628 DUK_INTERNAL duk_hstring *duk_to_property_key_hstring(duk_hthread *thr, duk_idx_t idx) {
20629 	duk_hstring *h;
20630 
20631 	DUK_ASSERT_API_ENTRY(thr);
20632 
20633 	duk_to_primitive(thr, idx, DUK_HINT_STRING);  /* needed for e.g. Symbol objects */
20634 	h = duk_get_hstring(thr, idx);
20635 	if (h == NULL) {
20636 		/* The "is string?" check may seem unnecessary, but as things
20637 		 * are duk_to_hstring() invokes ToString() which fails for
20638 		 * symbols.  But since symbols are already strings for Duktape
20639 		 * C API, we check for that before doing the coercion.
20640 		 */
20641 		h = duk_to_hstring(thr, idx);
20642 	}
20643 	DUK_ASSERT(h != NULL);
20644 	return h;
20645 }
20646 
20647 #if defined(DUK_USE_DEBUGGER_SUPPORT)  /* only needed by debugger for now */
duk_safe_to_hstring(duk_hthread * thr,duk_idx_t idx)20648 DUK_INTERNAL duk_hstring *duk_safe_to_hstring(duk_hthread *thr, duk_idx_t idx) {
20649 	DUK_ASSERT_API_ENTRY(thr);
20650 
20651 	(void) duk_safe_to_string(thr, idx);
20652 	DUK_ASSERT(duk_is_string(thr, idx));
20653 	DUK_ASSERT(duk_get_hstring(thr, idx) != NULL);
20654 	return duk_known_hstring(thr, idx);
20655 }
20656 #endif
20657 
20658 /* Push Object.prototype.toString() output for 'tv'. */
20659 #if 0  /* See XXX note why this variant doesn't work. */
20660 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20661 	duk_uint_t stridx_bidx = 0;  /* (prototype_bidx << 16) + default_tag_stridx */
20662 
20663 	DUK_ASSERT_API_ENTRY(thr);
20664 
20665 	/* Conceptually for any non-undefined/null value we should do a
20666 	 * ToObject() coercion and look up @@toStringTag (from the object
20667 	 * prototype) to see if a custom tag should be used.  Avoid the
20668 	 * actual conversion by doing a prototype lookup without the object
20669 	 * coercion.  However, see problem below.
20670 	 */
20671 
20672 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20673 
20674 	switch (DUK_TVAL_GET_TAG(tv)) {
20675 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20676 	case DUK_TAG_UNDEFINED: {
20677 		stridx_bidx = DUK_STRIDX_UC_UNDEFINED;
20678 		goto use_stridx;
20679 	}
20680 	case DUK_TAG_NULL: {
20681 		stridx_bidx = DUK_STRIDX_UC_NULL;
20682 		goto use_stridx;
20683 	}
20684 	case DUK_TAG_BOOLEAN: {
20685 		stridx_bidx = (DUK_BIDX_BOOLEAN_PROTOTYPE << 16) + DUK_STRIDX_UC_BOOLEAN;
20686 		goto use_proto_bidx;
20687 	}
20688 	case DUK_TAG_POINTER: {
20689 		stridx_bidx = (DUK_BIDX_POINTER_PROTOTYPE << 16) + DUK_STRIDX_UC_POINTER;
20690 		goto use_proto_bidx;
20691 	}
20692 	case DUK_TAG_LIGHTFUNC: {
20693 		stridx_bidx = (DUK_BIDX_FUNCTION_PROTOTYPE << 16) + DUK_STRIDX_UC_FUNCTION;
20694 		goto use_proto_bidx;
20695 	}
20696 	case DUK_TAG_STRING: {
20697 		duk_hstring *h;
20698 		h = DUK_TVAL_GET_STRING(tv);
20699 		DUK_ASSERT(h != NULL);
20700 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20701 			/* Even without DUK_USE_SYMBOL_BUILTIN the Symbol
20702 			 * prototype exists so we can lookup @@toStringTag
20703 			 * and provide [object Symbol] for symbol values
20704 			 * created from C code.
20705 			 */
20706 			stridx_bidx = (DUK_BIDX_SYMBOL_PROTOTYPE << 16) + DUK_STRIDX_UC_SYMBOL;
20707 		} else {
20708 			stridx_bidx = (DUK_BIDX_STRING_PROTOTYPE << 16) + DUK_STRIDX_UC_STRING;
20709 		}
20710 		goto use_proto_bidx;
20711 	}
20712 	case DUK_TAG_OBJECT: {
20713 		duk_push_tval(thr, tv);
20714 		stridx_bidx = 0xffffffffUL;  /* Marker value. */
20715 		goto use_pushed_object;
20716 	}
20717 	case DUK_TAG_BUFFER: {
20718 		stridx_bidx = (DUK_BIDX_UINT8ARRAY_PROTOTYPE << 16) + DUK_STRIDX_UINT8_ARRAY;
20719 		goto use_proto_bidx;
20720 	}
20721 #if defined(DUK_USE_FASTINT)
20722 	case DUK_TAG_FASTINT:
20723 		/* Fall through to generic number case. */
20724 #endif
20725 	default: {
20726 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));  /* number (maybe fastint) */
20727 		stridx_bidx = (DUK_BIDX_NUMBER_PROTOTYPE << 16) + DUK_STRIDX_UC_NUMBER;
20728 		goto use_proto_bidx;
20729 	}
20730 	}
20731 	DUK_ASSERT(0);  /* Never here. */
20732 
20733  use_proto_bidx:
20734 	DUK_ASSERT_BIDX_VALID((stridx_bidx >> 16) & 0xffffUL);
20735 	duk_push_hobject(thr, thr->builtins[(stridx_bidx >> 16) & 0xffffUL]);
20736 	/* Fall through. */
20737 
20738  use_pushed_object:
20739 	/* [ ... "[object" obj ] */
20740 
20741 #if defined(DUK_USE_SYMBOL_BUILTIN)
20742 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20743 	 * without Proxy or getter side effects, and use it in sanitized
20744 	 * form if it's a string.
20745 	 */
20746 	if (!avoid_side_effects) {
20747 		/* XXX: The problem with using the prototype object as the
20748 		 * lookup base is that if @@toStringTag is a getter, its
20749 		 * 'this' binding must be the ToObject() coerced input value,
20750 		 * not the prototype object of the type.
20751 		 */
20752 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20753 		if (duk_is_string_notsymbol(thr, -1)) {
20754 			duk_remove_m2(thr);
20755 			goto finish;
20756 		}
20757 		duk_pop_unsafe(thr);
20758 	}
20759 #endif
20760 
20761 	if (stridx_bidx == 0xffffffffUL) {
20762 		duk_hobject *h_obj;
20763 		duk_small_uint_t classnum;
20764 
20765 		h_obj = duk_known_hobject(thr, -1);
20766 		DUK_ASSERT(h_obj != NULL);
20767 		classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20768 		stridx_bidx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20769 	} else {
20770 		/* stridx_bidx already has the desired fallback stridx. */
20771 		;
20772 	}
20773 	duk_pop_unsafe(thr);
20774 	/* Fall through. */
20775 
20776  use_stridx:
20777 	/* [ ... "[object" ] */
20778 	duk_push_hstring_stridx(thr, stridx_bidx & 0xffffUL);
20779 
20780  finish:
20781 	/* [ ... "[object" tag ] */
20782 	duk_push_literal(thr, "]");
20783 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20784 }
20785 #endif  /* 0 */
20786 
duk_push_class_string_tval(duk_hthread * thr,duk_tval * tv,duk_bool_t avoid_side_effects)20787 DUK_INTERNAL void duk_push_class_string_tval(duk_hthread *thr, duk_tval *tv, duk_bool_t avoid_side_effects) {
20788 	duk_hobject *h_obj;
20789 	duk_small_uint_t classnum;
20790 	duk_small_uint_t stridx;
20791 	duk_tval tv_tmp;
20792 
20793 	DUK_ASSERT_API_ENTRY(thr);
20794 	DUK_ASSERT(tv != NULL);
20795 
20796 	/* Stabilize 'tv', duk_push_literal() may trigger side effects. */
20797 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
20798 	tv = &tv_tmp;
20799 
20800 	/* Conceptually for any non-undefined/null value we should do a
20801 	 * ToObject() coercion and look up @@toStringTag (from the object
20802 	 * prototype) to see if a custom result should be used.  We'd like to
20803 	 * avoid the actual conversion, but even for primitive types the
20804 	 * prototype may have @@toStringTag.  What's worse, the @@toStringTag
20805 	 * property may be a getter that must get the object coerced value
20806 	 * (not the prototype) as its 'this' binding.
20807 	 *
20808 	 * For now, do an actual object coercion.  This could be avoided by
20809 	 * doing a side effect free lookup to see if a getter would be invoked.
20810 	 * If not, the value can be read directly and the object coercion could
20811 	 * be avoided.  This may not be worth it in practice, because
20812 	 * Object.prototype.toString() is usually not performance critical.
20813 	 */
20814 
20815 	duk_push_literal(thr, "[object ");  /* -> [ ... "[object" ] */
20816 
20817 	switch (DUK_TVAL_GET_TAG(tv)) {
20818 	case DUK_TAG_UNUSED:  /* Treat like 'undefined', shouldn't happen. */
20819 	case DUK_TAG_UNDEFINED: {
20820 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_UNDEFINED);
20821 		goto finish;
20822 	}
20823 	case DUK_TAG_NULL: {
20824 		duk_push_hstring_stridx(thr, DUK_STRIDX_UC_NULL);
20825 		goto finish;
20826 	}
20827 	}
20828 
20829 	duk_push_tval(thr, tv);
20830 	tv = NULL;  /* Invalidated by ToObject(). */
20831 	duk_to_object(thr, -1);
20832 
20833 	/* [ ... "[object" obj ] */
20834 
20835 #if defined(DUK_USE_SYMBOL_BUILTIN)
20836 	/* XXX: better handling with avoid_side_effects == 1; lookup tval
20837 	 * without Proxy or getter side effects, and use it in sanitized
20838 	 * form if it's a string.
20839 	 */
20840 	if (!avoid_side_effects) {
20841 		(void) duk_get_prop_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_TO_STRING_TAG);
20842 		if (duk_is_string_notsymbol(thr, -1)) {
20843 			duk_remove_m2(thr);
20844 			goto finish;
20845 		}
20846 		duk_pop_unsafe(thr);
20847 	}
20848 #else
20849 	DUK_UNREF(avoid_side_effects);
20850 #endif
20851 
20852 	h_obj = duk_known_hobject(thr, -1);
20853 	DUK_ASSERT(h_obj != NULL);
20854 	classnum = DUK_HOBJECT_GET_CLASS_NUMBER(h_obj);
20855 	stridx = DUK_HOBJECT_CLASS_NUMBER_TO_STRIDX(classnum);
20856 	duk_pop_unsafe(thr);
20857 	duk_push_hstring_stridx(thr, stridx);
20858 
20859  finish:
20860 	/* [ ... "[object" tag ] */
20861 	duk_push_literal(thr, "]");
20862 	duk_concat(thr, 3);  /* [ ... "[object" tag "]" ] -> [ ... res ] */
20863 }
20864 
20865 /* 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)20866 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) {
20867 	duk_tval *tv;
20868 	duk_tval tv_tmp;
20869 	duk_double_t d, dmin, dmax;
20870 	duk_int_t res;
20871 	duk_bool_t clamped = 0;
20872 
20873 	DUK_ASSERT_API_ENTRY(thr);
20874 
20875 	tv = duk_require_tval(thr, idx);
20876 	DUK_ASSERT(tv != NULL);
20877 	d = duk_js_tointeger(thr, tv);  /* E5 Section 9.4, ToInteger() */
20878 
20879 	dmin = (duk_double_t) minval;
20880 	dmax = (duk_double_t) maxval;
20881 
20882 	if (d < dmin) {
20883 		clamped = 1;
20884 		res = minval;
20885 		d = dmin;
20886 	} else if (d > dmax) {
20887 		clamped = 1;
20888 		res = maxval;
20889 		d = dmax;
20890 	} else {
20891 		res = (duk_int_t) d;
20892 	}
20893 	DUK_UNREF(d);  /* SCANBUILD: with suitable dmin/dmax limits 'd' is unused */
20894 	/* 'd' and 'res' agree here */
20895 
20896 	/* Relookup in case duk_js_tointeger() ends up e.g. coercing an object. */
20897 	tv = duk_get_tval(thr, idx);
20898 	DUK_ASSERT(tv != NULL);  /* not popped by side effect */
20899 	DUK_TVAL_SET_TVAL(&tv_tmp, tv);
20900 #if defined(DUK_USE_FASTINT)
20901 #if (DUK_INT_MAX <= 0x7fffffffL)
20902 	DUK_TVAL_SET_I32(tv, res);
20903 #else
20904 	/* Clamping needed if duk_int_t is 64 bits. */
20905 	if (res >= DUK_FASTINT_MIN && res <= DUK_FASTINT_MAX) {
20906 		DUK_TVAL_SET_FASTINT(tv, res);
20907 	} else {
20908 		DUK_TVAL_SET_NUMBER(tv, d);
20909 	}
20910 #endif
20911 #else
20912 	DUK_TVAL_SET_NUMBER(tv, d);  /* no need to incref */
20913 #endif
20914 	DUK_TVAL_DECREF(thr, &tv_tmp);  /* side effects */
20915 
20916 	if (out_clamped) {
20917 		*out_clamped = clamped;
20918 	} else {
20919 		/* coerced value is updated to value stack even when RangeError thrown */
20920 		if (clamped) {
20921 			DUK_ERROR_RANGE(thr, DUK_STR_NUMBER_OUTSIDE_RANGE);
20922 			DUK_WO_NORETURN(return 0;);
20923 		}
20924 	}
20925 
20926 	return res;
20927 }
20928 
duk_to_int_clamped(duk_hthread * thr,duk_idx_t idx,duk_idx_t minval,duk_idx_t maxval)20929 DUK_INTERNAL duk_int_t duk_to_int_clamped(duk_hthread *thr, duk_idx_t idx, duk_idx_t minval, duk_idx_t maxval) {
20930 	duk_bool_t dummy;
20931 
20932 	DUK_ASSERT_API_ENTRY(thr);
20933 
20934 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, &dummy);
20935 }
20936 
duk_to_int_check_range(duk_hthread * thr,duk_idx_t idx,duk_int_t minval,duk_int_t maxval)20937 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) {
20938 	DUK_ASSERT_API_ENTRY(thr);
20939 	return duk_to_int_clamped_raw(thr, idx, minval, maxval, NULL);  /* out_clamped==NULL -> RangeError if outside range */
20940 }
20941 
duk_to_string(duk_hthread * thr,duk_idx_t idx)20942 DUK_EXTERNAL const char *duk_to_string(duk_hthread *thr, duk_idx_t idx) {
20943 	duk_tval *tv;
20944 
20945 	DUK_ASSERT_API_ENTRY(thr);
20946 
20947 	idx = duk_require_normalize_index(thr, idx);
20948 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
20949 	DUK_ASSERT(tv != NULL);
20950 
20951 	switch (DUK_TVAL_GET_TAG(tv)) {
20952 	case DUK_TAG_UNDEFINED: {
20953 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_UNDEFINED);
20954 		break;
20955 	}
20956 	case DUK_TAG_NULL: {
20957 		duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
20958 		break;
20959 	}
20960 	case DUK_TAG_BOOLEAN: {
20961 		if (DUK_TVAL_GET_BOOLEAN(tv)) {
20962 			duk_push_hstring_stridx(thr, DUK_STRIDX_TRUE);
20963 		} else {
20964 			duk_push_hstring_stridx(thr, DUK_STRIDX_FALSE);
20965 		}
20966 		break;
20967 	}
20968 	case DUK_TAG_STRING: {
20969 		/* Nop for actual strings, TypeError for Symbols.
20970 		 * Because various internals rely on ToString() coercion of
20971 		 * internal strings, -allow- (NOP) string coercion for hidden
20972 		 * symbols.
20973 		 */
20974 #if 1
20975 		duk_hstring *h;
20976 		h = DUK_TVAL_GET_STRING(tv);
20977 		DUK_ASSERT(h != NULL);
20978 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
20979 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_STRING_COERCE_SYMBOL);
20980 			DUK_WO_NORETURN(goto skip_replace;);
20981 		} else {
20982 			goto skip_replace;
20983 		}
20984 #else
20985 		goto skip_replace;
20986 #endif
20987 		break;
20988 	}
20989 	case DUK_TAG_BUFFER: /* Go through Uint8Array.prototype.toString() for coercion. */
20990 	case DUK_TAG_OBJECT: {
20991 		/* Plain buffers: go through ArrayBuffer.prototype.toString()
20992 		 * for coercion.
20993 		 *
20994 		 * Symbol objects: duk_to_primitive() results in a plain symbol
20995 		 * value, and duk_to_string() then causes a TypeError.
20996 		 */
20997 		duk_to_primitive(thr, idx, DUK_HINT_STRING);
20998 		DUK_ASSERT(!duk_is_buffer(thr, idx));  /* ToPrimitive() must guarantee */
20999 		DUK_ASSERT(!duk_is_object(thr, idx));
21000 		return duk_to_string(thr, idx);  /* Note: recursive call */
21001 	}
21002 	case DUK_TAG_POINTER: {
21003 		void *ptr = DUK_TVAL_GET_POINTER(tv);
21004 		if (ptr != NULL) {
21005 			duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) ptr);
21006 		} else {
21007 			/* Represent a null pointer as 'null' to be consistent with
21008 			 * the JX format variant.  Native '%p' format for a NULL
21009 			 * pointer may be e.g. '(nil)'.
21010 			 */
21011 			duk_push_hstring_stridx(thr, DUK_STRIDX_LC_NULL);
21012 		}
21013 		break;
21014 	}
21015 	case DUK_TAG_LIGHTFUNC: {
21016 		/* Should match Function.prototype.toString() */
21017 		duk_push_lightfunc_tostring(thr, tv);
21018 		break;
21019 	}
21020 #if defined(DUK_USE_FASTINT)
21021 	case DUK_TAG_FASTINT:
21022 #endif
21023 	default: {
21024 		/* number */
21025 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21026 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21027 		duk_push_tval(thr, tv);
21028 		duk_numconv_stringify(thr,
21029 		                      10 /*radix*/,
21030 		                      0 /*precision:shortest*/,
21031 		                      0 /*force_exponential*/);
21032 		break;
21033 	}
21034 	}
21035 
21036 	duk_replace(thr, idx);
21037 
21038  skip_replace:
21039 	DUK_ASSERT(duk_is_string(thr, idx));
21040 	return duk_require_string(thr, idx);
21041 }
21042 
duk_to_hstring(duk_hthread * thr,duk_idx_t idx)21043 DUK_INTERNAL duk_hstring *duk_to_hstring(duk_hthread *thr, duk_idx_t idx) {
21044 	duk_hstring *ret;
21045 
21046 	DUK_ASSERT_API_ENTRY(thr);
21047 
21048 	duk_to_string(thr, idx);
21049 	ret = duk_get_hstring(thr, idx);
21050 	DUK_ASSERT(ret != NULL);
21051 	return ret;
21052 }
21053 
duk_to_hstring_m1(duk_hthread * thr)21054 DUK_INTERNAL duk_hstring *duk_to_hstring_m1(duk_hthread *thr) {
21055 	DUK_ASSERT_API_ENTRY(thr);
21056 	return duk_to_hstring(thr, -1);
21057 }
21058 
duk_to_hstring_acceptsymbol(duk_hthread * thr,duk_idx_t idx)21059 DUK_INTERNAL duk_hstring *duk_to_hstring_acceptsymbol(duk_hthread *thr, duk_idx_t idx) {
21060 	duk_hstring *ret;
21061 
21062 	DUK_ASSERT_API_ENTRY(thr);
21063 
21064 	ret = duk_get_hstring(thr, idx);
21065 	if (DUK_UNLIKELY(ret && DUK_HSTRING_HAS_SYMBOL(ret))) {
21066 		return ret;
21067 	}
21068 	return duk_to_hstring(thr, idx);
21069 }
21070 
21071 /* Convert a plain buffer or any buffer object into a string, using the buffer
21072  * bytes 1:1 in the internal string representation.  For views the active byte
21073  * slice (not element slice interpreted as an initializer) is used.  This is
21074  * necessary in Duktape 2.x because ToString(plainBuffer) no longer creates a
21075  * string with the same bytes as in the buffer but rather (usually)
21076  * '[object ArrayBuffer]'.
21077  */
duk_buffer_to_string(duk_hthread * thr,duk_idx_t idx)21078 DUK_EXTERNAL const char *duk_buffer_to_string(duk_hthread *thr, duk_idx_t idx) {
21079 	void *ptr_src;
21080 	duk_size_t len;
21081 	const char *res;
21082 
21083 	DUK_ASSERT_API_ENTRY(thr);
21084 
21085 	idx = duk_require_normalize_index(thr, idx);
21086 
21087 	ptr_src = duk_require_buffer_data(thr, idx, &len);
21088 	DUK_ASSERT(ptr_src != NULL || len == 0);
21089 
21090 	res = duk_push_lstring(thr, (const char *) ptr_src, len);
21091 	duk_replace(thr, idx);
21092 	return res;
21093 }
21094 
duk_to_buffer_raw(duk_hthread * thr,duk_idx_t idx,duk_size_t * out_size,duk_uint_t mode)21095 DUK_EXTERNAL void *duk_to_buffer_raw(duk_hthread *thr, duk_idx_t idx, duk_size_t *out_size, duk_uint_t mode) {
21096 	duk_hbuffer *h_buf;
21097 	const duk_uint8_t *src_data;
21098 	duk_size_t src_size;
21099 	duk_uint8_t *dst_data;
21100 
21101 	DUK_ASSERT_API_ENTRY(thr);
21102 
21103 	idx = duk_require_normalize_index(thr, idx);
21104 
21105 	h_buf = duk_get_hbuffer(thr, idx);
21106 	if (h_buf != NULL) {
21107 		/* Buffer is kept as is, with the fixed/dynamic nature of the
21108 		 * buffer only changed if requested.  An external buffer
21109 		 * is converted into a non-external dynamic buffer in a
21110 		 * duk_to_dynamic_buffer() call.
21111 		 */
21112 		duk_uint_t tmp;
21113 		duk_uint8_t *tmp_ptr;
21114 
21115 		tmp_ptr = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf);
21116 		src_data = (const duk_uint8_t *) tmp_ptr;
21117 		src_size = DUK_HBUFFER_GET_SIZE(h_buf);
21118 
21119 		tmp = (DUK_HBUFFER_HAS_DYNAMIC(h_buf) ? DUK_BUF_MODE_DYNAMIC : DUK_BUF_MODE_FIXED);
21120 		if ((tmp == mode && !DUK_HBUFFER_HAS_EXTERNAL(h_buf)) ||
21121 		    mode == DUK_BUF_MODE_DONTCARE) {
21122 			/* Note: src_data may be NULL if input is a zero-size
21123 			 * dynamic buffer.
21124 			 */
21125 			dst_data = tmp_ptr;
21126 			goto skip_copy;
21127 		}
21128 	} else {
21129 		/* Non-buffer value is first ToString() coerced, then converted
21130 		 * to a buffer (fixed buffer is used unless a dynamic buffer is
21131 		 * explicitly requested).  Symbols are rejected with a TypeError.
21132 		 * XXX: C API could maybe allow symbol-to-buffer coercion?
21133 		 */
21134 		src_data = (const duk_uint8_t *) duk_to_lstring(thr, idx, &src_size);
21135 	}
21136 
21137 	dst_data = (duk_uint8_t *) duk_push_buffer(thr, src_size, (mode == DUK_BUF_MODE_DYNAMIC) /*dynamic*/);
21138 	/* dst_data may be NULL if size is zero. */
21139 	duk_memcpy_unsafe((void *) dst_data, (const void *) src_data, (size_t) src_size);
21140 
21141 	duk_replace(thr, idx);
21142  skip_copy:
21143 
21144 	if (out_size) {
21145 		*out_size = src_size;
21146 	}
21147 	return dst_data;
21148 }
21149 
duk_to_pointer(duk_hthread * thr,duk_idx_t idx)21150 DUK_EXTERNAL void *duk_to_pointer(duk_hthread *thr, duk_idx_t idx) {
21151 	duk_tval *tv;
21152 	void *res;
21153 
21154 	DUK_ASSERT_API_ENTRY(thr);
21155 
21156 	idx = duk_require_normalize_index(thr, idx);
21157 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21158 	DUK_ASSERT(tv != NULL);
21159 
21160 	switch (DUK_TVAL_GET_TAG(tv)) {
21161 	case DUK_TAG_UNDEFINED:
21162 	case DUK_TAG_NULL:
21163 	case DUK_TAG_BOOLEAN:
21164 		res = NULL;
21165 		break;
21166 	case DUK_TAG_POINTER:
21167 		res = DUK_TVAL_GET_POINTER(tv);
21168 		break;
21169 	case DUK_TAG_STRING:
21170 	case DUK_TAG_OBJECT:
21171 	case DUK_TAG_BUFFER:
21172 		/* Heap allocated: return heap pointer which is NOT useful
21173 		 * for the caller, except for debugging.
21174 		 */
21175 		res = (void *) DUK_TVAL_GET_HEAPHDR(tv);
21176 		break;
21177 	case DUK_TAG_LIGHTFUNC:
21178 		/* Function pointers do not always cast correctly to void *
21179 		 * (depends on memory and segmentation model for instance),
21180 		 * so they coerce to NULL.
21181 		 */
21182 		res = NULL;
21183 		break;
21184 #if defined(DUK_USE_FASTINT)
21185 	case DUK_TAG_FASTINT:
21186 #endif
21187 	default:
21188 		/* number */
21189 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21190 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21191 		res = NULL;
21192 		break;
21193 	}
21194 
21195 	duk_push_pointer(thr, res);
21196 	duk_replace(thr, idx);
21197 	return res;
21198 }
21199 
duk__push_func_from_lightfunc(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)21200 DUK_LOCAL void duk__push_func_from_lightfunc(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
21201 	duk_idx_t nargs;
21202 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21203 	duk_small_uint_t lf_len;
21204 	duk_hnatfunc *nf;
21205 
21206 	nargs = (duk_idx_t) DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
21207 	if (nargs == DUK_LFUNC_NARGS_VARARGS) {
21208 		nargs = (duk_idx_t) DUK_VARARGS;
21209 	}
21210 
21211 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21212 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
21213 	        DUK_HOBJECT_FLAG_CALLABLE |
21214 	        DUK_HOBJECT_FLAG_FASTREFS |
21215 	        DUK_HOBJECT_FLAG_NATFUNC |
21216 	        DUK_HOBJECT_FLAG_NEWENV |
21217 	        DUK_HOBJECT_FLAG_STRICT |
21218 	        DUK_HOBJECT_FLAG_NOTAIL |
21219 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
21220 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
21221 
21222 	lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
21223 	if ((duk_idx_t) lf_len != nargs) {
21224 		/* Explicit length is only needed if it differs from 'nargs'. */
21225 		duk_push_int(thr, (duk_int_t) lf_len);
21226 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_NONE);
21227 	}
21228 
21229 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
21230 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
21231 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
21232 #endif
21233 
21234 	nf = duk_known_hnatfunc(thr, -1);
21235 	nf->magic = (duk_int16_t) DUK_LFUNC_FLAGS_GET_MAGIC(lf_flags);
21236 }
21237 
duk_to_object(duk_hthread * thr,duk_idx_t idx)21238 DUK_EXTERNAL void duk_to_object(duk_hthread *thr, duk_idx_t idx) {
21239 	duk_tval *tv;
21240 	duk_uint_t flags = 0;   /* shared flags for a subset of types */
21241 	duk_small_int_t proto = 0;
21242 
21243 	DUK_ASSERT_API_ENTRY(thr);
21244 
21245 	idx = duk_require_normalize_index(thr, idx);
21246 	tv = DUK_GET_TVAL_POSIDX(thr, idx);
21247 	DUK_ASSERT(tv != NULL);
21248 
21249 	switch (DUK_TVAL_GET_TAG(tv)) {
21250 #if !defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21251 	case DUK_TAG_BUFFER:  /* With no bufferobject support, don't object coerce. */
21252 #endif
21253 	case DUK_TAG_UNDEFINED:
21254 	case DUK_TAG_NULL: {
21255 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
21256 		DUK_WO_NORETURN(return;);
21257 		break;
21258 	}
21259 	case DUK_TAG_BOOLEAN: {
21260 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21261 		        DUK_HOBJECT_FLAG_FASTREFS |
21262 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_BOOLEAN);
21263 		proto = DUK_BIDX_BOOLEAN_PROTOTYPE;
21264 		goto create_object;
21265 	}
21266 	case DUK_TAG_STRING: {
21267 		duk_hstring *h;
21268 		h = DUK_TVAL_GET_STRING(tv);
21269 		DUK_ASSERT(h != NULL);
21270 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
21271 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21272 			        DUK_HOBJECT_FLAG_FASTREFS |
21273 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_SYMBOL);
21274 			proto = DUK_BIDX_SYMBOL_PROTOTYPE;
21275 		} else {
21276 			flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21277 			        DUK_HOBJECT_FLAG_FASTREFS |
21278 			        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
21279 			        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
21280 			proto = DUK_BIDX_STRING_PROTOTYPE;
21281 		}
21282 		goto create_object;
21283 	}
21284 	case DUK_TAG_OBJECT: {
21285 		/* nop */
21286 		break;
21287 	}
21288 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
21289 	case DUK_TAG_BUFFER: {
21290 		/* A plain buffer object coerces to a full ArrayBuffer which
21291 		 * is not fully transparent behavior (ToObject() should be a
21292 		 * nop for an object).  This behavior matches lightfuncs which
21293 		 * also coerce to an equivalent Function object.  There are
21294 		 * also downsides to defining ToObject(plainBuffer) as a no-op;
21295 		 * for example duk_to_hobject() could result in a NULL pointer.
21296 		 */
21297 		duk_hbuffer *h_buf;
21298 
21299 		h_buf = DUK_TVAL_GET_BUFFER(tv);
21300 		DUK_ASSERT(h_buf != NULL);
21301 		duk_hbufobj_push_uint8array_from_plain(thr, h_buf);
21302 		goto replace_value;
21303 	}
21304 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21305 	case DUK_TAG_POINTER: {
21306 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21307 		        DUK_HOBJECT_FLAG_FASTREFS |
21308 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER);
21309 		proto = DUK_BIDX_POINTER_PROTOTYPE;
21310 		goto create_object;
21311 	}
21312 	case DUK_TAG_LIGHTFUNC: {
21313 		/* Lightfunc coerces to a Function instance with concrete
21314 		 * properties.  Since 'length' is virtual for Duktape/C
21315 		 * functions, don't need to define that.  The result is made
21316 		 * extensible to mimic what happens to strings in object
21317 		 * coercion:
21318 		 *
21319 		 *   > Object.isExtensible(Object('foo'))
21320 		 *   true
21321 		 */
21322 		duk_small_uint_t lf_flags;
21323 		duk_c_function func;
21324 
21325 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
21326 		duk__push_func_from_lightfunc(thr, func, lf_flags);
21327 		goto replace_value;
21328 	}
21329 #if defined(DUK_USE_FASTINT)
21330 	case DUK_TAG_FASTINT:
21331 #endif
21332 	default: {
21333 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21334 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21335 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
21336 		        DUK_HOBJECT_FLAG_FASTREFS |
21337 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_NUMBER);
21338 		proto = DUK_BIDX_NUMBER_PROTOTYPE;
21339 		goto create_object;
21340 	}
21341 	}
21342 	DUK_ASSERT(duk_is_object(thr, idx));
21343 	return;
21344 
21345  create_object:
21346 	(void) duk_push_object_helper(thr, flags, proto);
21347 
21348 	/* Note: Boolean prototype's internal value property is not writable,
21349 	 * but duk_xdef_prop_stridx() disregards the write protection.  Boolean
21350 	 * instances are immutable.
21351 	 *
21352 	 * String and buffer special behaviors are already enabled which is not
21353 	 * ideal, but a write to the internal value is not affected by them.
21354 	 */
21355 	duk_dup(thr, idx);
21356 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
21357 
21358  replace_value:
21359 	duk_replace(thr, idx);
21360 	DUK_ASSERT(duk_is_object(thr, idx));
21361 }
21362 
duk_to_hobject(duk_hthread * thr,duk_idx_t idx)21363 DUK_INTERNAL duk_hobject *duk_to_hobject(duk_hthread *thr, duk_idx_t idx) {
21364 	duk_hobject *ret;
21365 
21366 	DUK_ASSERT_API_ENTRY(thr);
21367 
21368 	duk_to_object(thr, idx);
21369 	ret = duk_known_hobject(thr, idx);
21370 	return ret;
21371 }
21372 
21373 /*
21374  *  Type checking
21375  */
21376 
duk__tag_check(duk_hthread * thr,duk_idx_t idx,duk_small_uint_t tag)21377 DUK_LOCAL duk_bool_t duk__tag_check(duk_hthread *thr, duk_idx_t idx, duk_small_uint_t tag) {
21378 	duk_tval *tv;
21379 
21380 	tv = duk_get_tval_or_unused(thr, idx);
21381 	DUK_ASSERT(tv != NULL);
21382 	return (DUK_TVAL_GET_TAG(tv) == tag);
21383 }
21384 
duk__obj_flag_any_default_false(duk_hthread * thr,duk_idx_t idx,duk_uint_t flag_mask)21385 DUK_LOCAL duk_bool_t duk__obj_flag_any_default_false(duk_hthread *thr, duk_idx_t idx, duk_uint_t flag_mask) {
21386 	duk_hobject *obj;
21387 
21388 	DUK_ASSERT_API_ENTRY(thr);
21389 
21390 	obj = duk_get_hobject(thr, idx);
21391 	if (obj) {
21392 		return (DUK_HEAPHDR_CHECK_FLAG_BITS((duk_heaphdr *) obj, flag_mask) ? 1 : 0);
21393 	}
21394 	return 0;
21395 }
21396 
duk_get_type_tval(duk_tval * tv)21397 DUK_INTERNAL duk_int_t duk_get_type_tval(duk_tval *tv) {
21398 	DUK_ASSERT(tv != NULL);
21399 
21400 #if defined(DUK_USE_PACKED_TVAL)
21401 	switch (DUK_TVAL_GET_TAG(tv)) {
21402 	case DUK_TAG_UNUSED:
21403 		return DUK_TYPE_NONE;
21404 	case DUK_TAG_UNDEFINED:
21405 		return DUK_TYPE_UNDEFINED;
21406 	case DUK_TAG_NULL:
21407 		return DUK_TYPE_NULL;
21408 	case DUK_TAG_BOOLEAN:
21409 		return DUK_TYPE_BOOLEAN;
21410 	case DUK_TAG_STRING:
21411 		return DUK_TYPE_STRING;
21412 	case DUK_TAG_OBJECT:
21413 		return DUK_TYPE_OBJECT;
21414 	case DUK_TAG_BUFFER:
21415 		return DUK_TYPE_BUFFER;
21416 	case DUK_TAG_POINTER:
21417 		return DUK_TYPE_POINTER;
21418 	case DUK_TAG_LIGHTFUNC:
21419 		return DUK_TYPE_LIGHTFUNC;
21420 #if defined(DUK_USE_FASTINT)
21421 	case DUK_TAG_FASTINT:
21422 #endif
21423 	default:
21424 		/* Note: number has no explicit tag (in 8-byte representation) */
21425 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21426 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21427 		return DUK_TYPE_NUMBER;
21428 	}
21429 #else  /* DUK_USE_PACKED_TVAL */
21430 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21431 	DUK_ASSERT(sizeof(duk__type_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21432 	return (duk_int_t) duk__type_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21433 #endif  /* DUK_USE_PACKED_TVAL */
21434 }
21435 
duk_get_type(duk_hthread * thr,duk_idx_t idx)21436 DUK_EXTERNAL duk_int_t duk_get_type(duk_hthread *thr, duk_idx_t idx) {
21437 	duk_tval *tv;
21438 
21439 	DUK_ASSERT_API_ENTRY(thr);
21440 
21441 	tv = duk_get_tval_or_unused(thr, idx);
21442 	DUK_ASSERT(tv != NULL);
21443 
21444 	return duk_get_type_tval(tv);
21445 }
21446 
21447 #if defined(DUK_USE_VERBOSE_ERRORS) && defined(DUK_USE_PARANOID_ERRORS)
21448 DUK_LOCAL const char * const duk__type_names[] = {
21449 	"none",
21450 	"undefined",
21451 	"null",
21452 	"boolean",
21453 	"number",
21454 	"string",
21455 	"object",
21456 	"buffer",
21457 	"pointer",
21458 	"lightfunc"
21459 };
21460 
duk_get_type_name(duk_hthread * thr,duk_idx_t idx)21461 DUK_INTERNAL const char *duk_get_type_name(duk_hthread *thr, duk_idx_t idx) {
21462 	duk_int_t type_tag;
21463 
21464 	DUK_ASSERT_API_ENTRY(thr);
21465 
21466 	type_tag = duk_get_type(thr, idx);
21467 	DUK_ASSERT(type_tag >= DUK_TYPE_MIN && type_tag <= DUK_TYPE_MAX);
21468 	DUK_ASSERT(DUK_TYPE_MIN == 0 && sizeof(duk__type_names) / sizeof(const char *) == DUK_TYPE_MAX + 1);
21469 
21470 	return duk__type_names[type_tag];
21471 }
21472 #endif  /* DUK_USE_VERBOSE_ERRORS && DUK_USE_PARANOID_ERRORS */
21473 
duk_get_class_number(duk_hthread * thr,duk_idx_t idx)21474 DUK_INTERNAL duk_small_uint_t duk_get_class_number(duk_hthread *thr, duk_idx_t idx) {
21475 	duk_tval *tv;
21476 	duk_hobject *obj;
21477 
21478 	DUK_ASSERT_API_ENTRY(thr);
21479 
21480 	tv = duk_get_tval_or_unused(thr, idx);
21481 	DUK_ASSERT(tv != NULL);
21482 
21483 	switch (DUK_TVAL_GET_TAG(tv)) {
21484 	case DUK_TAG_OBJECT:
21485 		obj = DUK_TVAL_GET_OBJECT(tv);
21486 		DUK_ASSERT(obj != NULL);
21487 		return DUK_HOBJECT_GET_CLASS_NUMBER(obj);
21488 	case DUK_TAG_BUFFER:
21489 		/* Buffers behave like Uint8Array objects. */
21490 		return DUK_HOBJECT_CLASS_UINT8ARRAY;
21491 	case DUK_TAG_LIGHTFUNC:
21492 		/* Lightfuncs behave like Function objects. */
21493 		return DUK_HOBJECT_CLASS_FUNCTION;
21494 	default:
21495 		/* Primitive or UNUSED, no class number. */
21496 		return DUK_HOBJECT_CLASS_NONE;
21497 	}
21498 }
21499 
duk_check_type(duk_hthread * thr,duk_idx_t idx,duk_int_t type)21500 DUK_EXTERNAL duk_bool_t duk_check_type(duk_hthread *thr, duk_idx_t idx, duk_int_t type) {
21501 	DUK_ASSERT_API_ENTRY(thr);
21502 
21503 	return (duk_get_type(thr, idx) == type) ? 1 : 0;
21504 }
21505 
duk_get_type_mask_tval(duk_tval * tv)21506 DUK_INTERNAL duk_uint_t duk_get_type_mask_tval(duk_tval *tv) {
21507 	DUK_ASSERT(tv != NULL);
21508 
21509 #if defined(DUK_USE_PACKED_TVAL)
21510 	switch (DUK_TVAL_GET_TAG(tv)) {
21511 	case DUK_TAG_UNUSED:
21512 		return DUK_TYPE_MASK_NONE;
21513 	case DUK_TAG_UNDEFINED:
21514 		return DUK_TYPE_MASK_UNDEFINED;
21515 	case DUK_TAG_NULL:
21516 		return DUK_TYPE_MASK_NULL;
21517 	case DUK_TAG_BOOLEAN:
21518 		return DUK_TYPE_MASK_BOOLEAN;
21519 	case DUK_TAG_STRING:
21520 		return DUK_TYPE_MASK_STRING;
21521 	case DUK_TAG_OBJECT:
21522 		return DUK_TYPE_MASK_OBJECT;
21523 	case DUK_TAG_BUFFER:
21524 		return DUK_TYPE_MASK_BUFFER;
21525 	case DUK_TAG_POINTER:
21526 		return DUK_TYPE_MASK_POINTER;
21527 	case DUK_TAG_LIGHTFUNC:
21528 		return DUK_TYPE_MASK_LIGHTFUNC;
21529 #if defined(DUK_USE_FASTINT)
21530 	case DUK_TAG_FASTINT:
21531 #endif
21532 	default:
21533 		/* Note: number has no explicit tag (in 8-byte representation) */
21534 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
21535 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
21536 		return DUK_TYPE_MASK_NUMBER;
21537 	}
21538 #else  /* DUK_USE_PACKED_TVAL */
21539 	DUK_ASSERT(DUK_TVAL_IS_VALID_TAG(tv));
21540 	DUK_ASSERT(sizeof(duk__type_mask_from_tag) / sizeof(duk_uint_t) == DUK_TAG_MAX - DUK_TAG_MIN + 1);
21541 	return duk__type_mask_from_tag[DUK_TVAL_GET_TAG(tv) - DUK_TAG_MIN];
21542 #endif  /* DUK_USE_PACKED_TVAL */
21543 }
21544 
duk_get_type_mask(duk_hthread * thr,duk_idx_t idx)21545 DUK_EXTERNAL duk_uint_t duk_get_type_mask(duk_hthread *thr, duk_idx_t idx) {
21546 	duk_tval *tv;
21547 
21548 	DUK_ASSERT_API_ENTRY(thr);
21549 
21550 	tv = duk_get_tval_or_unused(thr, idx);
21551 	DUK_ASSERT(tv != NULL);
21552 
21553 	return duk_get_type_mask_tval(tv);
21554 }
21555 
duk_check_type_mask(duk_hthread * thr,duk_idx_t idx,duk_uint_t mask)21556 DUK_EXTERNAL duk_bool_t duk_check_type_mask(duk_hthread *thr, duk_idx_t idx, duk_uint_t mask) {
21557 	DUK_ASSERT_API_ENTRY(thr);
21558 
21559 	if (DUK_LIKELY((duk_get_type_mask(thr, idx) & mask) != 0U)) {
21560 		return 1;
21561 	}
21562 	if (mask & DUK_TYPE_MASK_THROW) {
21563 		DUK_ERROR_TYPE(thr, DUK_STR_UNEXPECTED_TYPE);
21564 		DUK_WO_NORETURN(return 0;);
21565 	}
21566 	return 0;
21567 }
21568 
duk_is_undefined(duk_hthread * thr,duk_idx_t idx)21569 DUK_EXTERNAL duk_bool_t duk_is_undefined(duk_hthread *thr, duk_idx_t idx) {
21570 	DUK_ASSERT_API_ENTRY(thr);
21571 	return duk__tag_check(thr, idx, DUK_TAG_UNDEFINED);
21572 }
21573 
duk_is_null(duk_hthread * thr,duk_idx_t idx)21574 DUK_EXTERNAL duk_bool_t duk_is_null(duk_hthread *thr, duk_idx_t idx) {
21575 	DUK_ASSERT_API_ENTRY(thr);
21576 	return duk__tag_check(thr, idx, DUK_TAG_NULL);
21577 }
21578 
duk_is_boolean(duk_hthread * thr,duk_idx_t idx)21579 DUK_EXTERNAL duk_bool_t duk_is_boolean(duk_hthread *thr, duk_idx_t idx) {
21580 	DUK_ASSERT_API_ENTRY(thr);
21581 	return duk__tag_check(thr, idx, DUK_TAG_BOOLEAN);
21582 }
21583 
duk_is_number(duk_hthread * thr,duk_idx_t idx)21584 DUK_EXTERNAL duk_bool_t duk_is_number(duk_hthread *thr, duk_idx_t idx) {
21585 	duk_tval *tv;
21586 
21587 	DUK_ASSERT_API_ENTRY(thr);
21588 
21589 	/*
21590 	 *  Number is special because it doesn't have a specific
21591 	 *  tag in the 8-byte representation.
21592 	 */
21593 
21594 	/* XXX: shorter version for unpacked representation? */
21595 
21596 	tv = duk_get_tval_or_unused(thr, idx);
21597 	DUK_ASSERT(tv != NULL);
21598 	return DUK_TVAL_IS_NUMBER(tv);
21599 }
21600 
duk_is_nan(duk_hthread * thr,duk_idx_t idx)21601 DUK_EXTERNAL duk_bool_t duk_is_nan(duk_hthread *thr, duk_idx_t idx) {
21602 	/* XXX: This will now return false for non-numbers, even though they would
21603 	 * coerce to NaN (as a general rule).  In particular, duk_get_number()
21604 	 * returns a NaN for non-numbers, so should this function also return
21605 	 * true for non-numbers?
21606 	 */
21607 
21608 	duk_tval *tv;
21609 
21610 	DUK_ASSERT_API_ENTRY(thr);
21611 
21612 	tv = duk_get_tval_or_unused(thr, idx);
21613 	DUK_ASSERT(tv != NULL);
21614 
21615 	/* XXX: for packed duk_tval an explicit "is number" check is unnecessary */
21616 	if (!DUK_TVAL_IS_NUMBER(tv)) {
21617 		return 0;
21618 	}
21619 	return (duk_bool_t) DUK_ISNAN(DUK_TVAL_GET_NUMBER(tv));
21620 }
21621 
duk_is_string(duk_hthread * thr,duk_idx_t idx)21622 DUK_EXTERNAL duk_bool_t duk_is_string(duk_hthread *thr, duk_idx_t idx) {
21623 	DUK_ASSERT_API_ENTRY(thr);
21624 	return duk__tag_check(thr, idx, DUK_TAG_STRING);
21625 }
21626 
duk_is_string_notsymbol(duk_hthread * thr,duk_idx_t idx)21627 DUK_INTERNAL duk_bool_t duk_is_string_notsymbol(duk_hthread *thr, duk_idx_t idx) {
21628 	DUK_ASSERT_API_ENTRY(thr);
21629 	return duk_get_hstring_notsymbol(thr, idx) != NULL;
21630 }
21631 
duk_is_object(duk_hthread * thr,duk_idx_t idx)21632 DUK_EXTERNAL duk_bool_t duk_is_object(duk_hthread *thr, duk_idx_t idx) {
21633 	DUK_ASSERT_API_ENTRY(thr);
21634 	return duk__tag_check(thr, idx, DUK_TAG_OBJECT);
21635 }
21636 
duk_is_buffer(duk_hthread * thr,duk_idx_t idx)21637 DUK_EXTERNAL duk_bool_t duk_is_buffer(duk_hthread *thr, duk_idx_t idx) {
21638 	DUK_ASSERT_API_ENTRY(thr);
21639 	return duk__tag_check(thr, idx, DUK_TAG_BUFFER);
21640 }
21641 
21642 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21643 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21644 	duk_tval *tv;
21645 
21646 	DUK_ASSERT_API_ENTRY(thr);
21647 
21648 	tv = duk_get_tval_or_unused(thr, idx);
21649 	DUK_ASSERT(tv != NULL);
21650 	if (DUK_TVAL_IS_BUFFER(tv)) {
21651 		return 1;
21652 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
21653 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
21654 		DUK_ASSERT(h != NULL);
21655 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
21656 			return 1;
21657 		}
21658 	}
21659 	return 0;
21660 }
21661 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
duk_is_buffer_data(duk_hthread * thr,duk_idx_t idx)21662 DUK_EXTERNAL duk_bool_t duk_is_buffer_data(duk_hthread *thr, duk_idx_t idx) {
21663 	DUK_ASSERT_API_ENTRY(thr);
21664 
21665 	return duk_is_buffer(thr, idx);
21666 }
21667 
21668 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
21669 
duk_is_pointer(duk_hthread * thr,duk_idx_t idx)21670 DUK_EXTERNAL duk_bool_t duk_is_pointer(duk_hthread *thr, duk_idx_t idx) {
21671 	DUK_ASSERT_API_ENTRY(thr);
21672 	return duk__tag_check(thr, idx, DUK_TAG_POINTER);
21673 }
21674 
duk_is_lightfunc(duk_hthread * thr,duk_idx_t idx)21675 DUK_EXTERNAL duk_bool_t duk_is_lightfunc(duk_hthread *thr, duk_idx_t idx) {
21676 	DUK_ASSERT_API_ENTRY(thr);
21677 	return duk__tag_check(thr, idx, DUK_TAG_LIGHTFUNC);
21678 }
21679 
duk_is_symbol(duk_hthread * thr,duk_idx_t idx)21680 DUK_EXTERNAL duk_bool_t duk_is_symbol(duk_hthread *thr, duk_idx_t idx) {
21681 	duk_hstring *h;
21682 
21683 	DUK_ASSERT_API_ENTRY(thr);
21684 	h = duk_get_hstring(thr, idx);
21685 	/* Use DUK_LIKELY() here because caller may be more likely to type
21686 	 * check an expected symbol than not.
21687 	 */
21688 	if (DUK_LIKELY(h != NULL && DUK_HSTRING_HAS_SYMBOL(h))) {
21689 		return 1;
21690 	}
21691 	return 0;
21692 }
21693 
duk_is_array(duk_hthread * thr,duk_idx_t idx)21694 DUK_EXTERNAL duk_bool_t duk_is_array(duk_hthread *thr, duk_idx_t idx) {
21695 	duk_hobject *obj;
21696 
21697 	DUK_ASSERT_API_ENTRY(thr);
21698 
21699 	obj = duk_get_hobject(thr, idx);
21700 	if (obj) {
21701 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_ARRAY ? 1 : 0);
21702 	}
21703 	return 0;
21704 }
21705 
duk_is_function(duk_hthread * thr,duk_idx_t idx)21706 DUK_EXTERNAL duk_bool_t duk_is_function(duk_hthread *thr, duk_idx_t idx) {
21707 	duk_tval *tv;
21708 
21709 	DUK_ASSERT_API_ENTRY(thr);
21710 
21711 	tv = duk_get_tval_or_unused(thr, idx);
21712 	if (DUK_TVAL_IS_OBJECT(tv)) {
21713 		duk_hobject *h;
21714 		h = DUK_TVAL_GET_OBJECT(tv);
21715 		DUK_ASSERT(h != NULL);
21716 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21717 	}
21718 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21719 		return 1;
21720 	}
21721 	return 0;
21722 }
21723 
duk_is_callable_tval(duk_hthread * thr,duk_tval * tv)21724 DUK_INTERNAL duk_bool_t duk_is_callable_tval(duk_hthread *thr, duk_tval *tv) {
21725 	DUK_ASSERT_API_ENTRY(thr);
21726 
21727 	DUK_UNREF(thr);
21728 
21729 	if (DUK_TVAL_IS_OBJECT(tv)) {
21730 		duk_hobject *h;
21731 		h = DUK_TVAL_GET_OBJECT(tv);
21732 		DUK_ASSERT(h != NULL);
21733 		return DUK_HOBJECT_HAS_CALLABLE(h) ? 1 : 0;
21734 	}
21735 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21736 		return 1;
21737 	}
21738 	return 0;
21739 }
21740 
duk_is_constructable(duk_hthread * thr,duk_idx_t idx)21741 DUK_EXTERNAL duk_bool_t duk_is_constructable(duk_hthread *thr, duk_idx_t idx) {
21742 	duk_tval *tv;
21743 
21744 	DUK_ASSERT_API_ENTRY(thr);
21745 
21746 	tv = duk_get_tval_or_unused(thr, idx);
21747 	if (DUK_TVAL_IS_OBJECT(tv)) {
21748 		duk_hobject *h;
21749 		h = DUK_TVAL_GET_OBJECT(tv);
21750 		DUK_ASSERT(h != NULL);
21751 		return DUK_HOBJECT_HAS_CONSTRUCTABLE(h) ? 1 : 0;
21752 	}
21753 	if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
21754 		return 1;
21755 	}
21756 	return 0;
21757 }
21758 
duk_is_c_function(duk_hthread * thr,duk_idx_t idx)21759 DUK_EXTERNAL duk_bool_t duk_is_c_function(duk_hthread *thr, duk_idx_t idx) {
21760 	DUK_ASSERT_API_ENTRY(thr);
21761 	return duk__obj_flag_any_default_false(thr,
21762 	                                       idx,
21763 	                                       DUK_HOBJECT_FLAG_NATFUNC);
21764 }
21765 
duk_is_ecmascript_function(duk_hthread * thr,duk_idx_t idx)21766 DUK_EXTERNAL duk_bool_t duk_is_ecmascript_function(duk_hthread *thr, duk_idx_t idx) {
21767 	DUK_ASSERT_API_ENTRY(thr);
21768 	return duk__obj_flag_any_default_false(thr,
21769 	                                       idx,
21770 	                                       DUK_HOBJECT_FLAG_COMPFUNC);
21771 }
21772 
duk_is_bound_function(duk_hthread * thr,duk_idx_t idx)21773 DUK_EXTERNAL duk_bool_t duk_is_bound_function(duk_hthread *thr, duk_idx_t idx) {
21774 	DUK_ASSERT_API_ENTRY(thr);
21775 	return duk__obj_flag_any_default_false(thr,
21776 	                                       idx,
21777 	                                       DUK_HOBJECT_FLAG_BOUNDFUNC);
21778 }
21779 
duk_is_thread(duk_hthread * thr,duk_idx_t idx)21780 DUK_EXTERNAL duk_bool_t duk_is_thread(duk_hthread *thr, duk_idx_t idx) {
21781 	duk_hobject *obj;
21782 
21783 	DUK_ASSERT_API_ENTRY(thr);
21784 
21785 	obj = duk_get_hobject(thr, idx);
21786 	if (obj) {
21787 		return (DUK_HOBJECT_GET_CLASS_NUMBER(obj) == DUK_HOBJECT_CLASS_THREAD ? 1 : 0);
21788 	}
21789 	return 0;
21790 }
21791 
duk_is_fixed_buffer(duk_hthread * thr,duk_idx_t idx)21792 DUK_EXTERNAL duk_bool_t duk_is_fixed_buffer(duk_hthread *thr, duk_idx_t idx) {
21793 	duk_tval *tv;
21794 
21795 	DUK_ASSERT_API_ENTRY(thr);
21796 
21797 	tv = duk_get_tval_or_unused(thr, idx);
21798 	DUK_ASSERT(tv != NULL);
21799 	if (DUK_TVAL_IS_BUFFER(tv)) {
21800 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21801 		DUK_ASSERT(h != NULL);
21802 		return (DUK_HBUFFER_HAS_DYNAMIC(h) ? 0 : 1);
21803 	}
21804 	return 0;
21805 }
21806 
duk_is_dynamic_buffer(duk_hthread * thr,duk_idx_t idx)21807 DUK_EXTERNAL duk_bool_t duk_is_dynamic_buffer(duk_hthread *thr, duk_idx_t idx) {
21808 	duk_tval *tv;
21809 
21810 	DUK_ASSERT_API_ENTRY(thr);
21811 
21812 	tv = duk_get_tval_or_unused(thr, idx);
21813 	DUK_ASSERT(tv != NULL);
21814 	if (DUK_TVAL_IS_BUFFER(tv)) {
21815 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21816 		DUK_ASSERT(h != NULL);
21817 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21818 	}
21819 	return 0;
21820 }
21821 
duk_is_external_buffer(duk_hthread * thr,duk_idx_t idx)21822 DUK_EXTERNAL duk_bool_t duk_is_external_buffer(duk_hthread *thr, duk_idx_t idx) {
21823 	duk_tval *tv;
21824 
21825 	DUK_ASSERT_API_ENTRY(thr);
21826 
21827 	tv = duk_get_tval_or_unused(thr, idx);
21828 	DUK_ASSERT(tv != NULL);
21829 	if (DUK_TVAL_IS_BUFFER(tv)) {
21830 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
21831 		DUK_ASSERT(h != NULL);
21832 		return (DUK_HBUFFER_HAS_DYNAMIC(h) && DUK_HBUFFER_HAS_EXTERNAL(h) ? 1 : 0);
21833 	}
21834 	return 0;
21835 }
21836 
duk_get_error_code(duk_hthread * thr,duk_idx_t idx)21837 DUK_EXTERNAL duk_errcode_t duk_get_error_code(duk_hthread *thr, duk_idx_t idx) {
21838 	duk_hobject *h;
21839 	duk_uint_t sanity;
21840 
21841 	DUK_ASSERT_API_ENTRY(thr);
21842 
21843 	h = duk_get_hobject(thr, idx);
21844 
21845 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
21846 	do {
21847 		if (!h) {
21848 			return DUK_ERR_NONE;
21849 		}
21850 
21851 		/* XXX: something more convenient? */
21852 
21853 		if (h == thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE]) {
21854 			return DUK_ERR_EVAL_ERROR;
21855 		}
21856 		if (h == thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE]) {
21857 			return DUK_ERR_RANGE_ERROR;
21858 		}
21859 		if (h == thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE]) {
21860 			return DUK_ERR_REFERENCE_ERROR;
21861 		}
21862 		if (h == thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE]) {
21863 			return DUK_ERR_SYNTAX_ERROR;
21864 		}
21865 		if (h == thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE]) {
21866 			return DUK_ERR_TYPE_ERROR;
21867 		}
21868 		if (h == thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE]) {
21869 			return DUK_ERR_URI_ERROR;
21870 		}
21871 		if (h == thr->builtins[DUK_BIDX_ERROR_PROTOTYPE]) {
21872 			return DUK_ERR_ERROR;
21873 		}
21874 
21875 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
21876 	} while (--sanity > 0);
21877 
21878 	return DUK_ERR_NONE;
21879 }
21880 
21881 /*
21882  *  Pushers
21883  */
21884 
duk_push_tval(duk_hthread * thr,duk_tval * tv)21885 DUK_INTERNAL void duk_push_tval(duk_hthread *thr, duk_tval *tv) {
21886 	duk_tval *tv_slot;
21887 
21888 	DUK_ASSERT_API_ENTRY(thr);
21889 	DUK_ASSERT(tv != NULL);
21890 
21891 	DUK__CHECK_SPACE();
21892 	tv_slot = thr->valstack_top++;
21893 	DUK_TVAL_SET_TVAL(tv_slot, tv);
21894 	DUK_TVAL_INCREF(thr, tv);  /* no side effects */
21895 }
21896 
duk_push_undefined(duk_hthread * thr)21897 DUK_EXTERNAL void duk_push_undefined(duk_hthread *thr) {
21898 	DUK_ASSERT_API_ENTRY(thr);
21899 
21900 	DUK__CHECK_SPACE();
21901 
21902 	/* Because value stack init policy is 'undefined above top',
21903 	 * we don't need to write, just assert.
21904 	 */
21905 	thr->valstack_top++;
21906 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
21907 }
21908 
duk_push_null(duk_hthread * thr)21909 DUK_EXTERNAL void duk_push_null(duk_hthread *thr) {
21910 	duk_tval *tv_slot;
21911 
21912 	DUK_ASSERT_API_ENTRY(thr);
21913 	DUK__CHECK_SPACE();
21914 	tv_slot = thr->valstack_top++;
21915 	DUK_TVAL_SET_NULL(tv_slot);
21916 }
21917 
duk_push_boolean(duk_hthread * thr,duk_bool_t val)21918 DUK_EXTERNAL void duk_push_boolean(duk_hthread *thr, duk_bool_t val) {
21919 	duk_tval *tv_slot;
21920 	duk_small_int_t b;
21921 
21922 	DUK_ASSERT_API_ENTRY(thr);
21923 	DUK__CHECK_SPACE();
21924 	b = (val ? 1 : 0);  /* ensure value is 1 or 0 (not other non-zero) */
21925 	tv_slot = thr->valstack_top++;
21926 	DUK_TVAL_SET_BOOLEAN(tv_slot, b);
21927 }
21928 
duk_push_true(duk_hthread * thr)21929 DUK_EXTERNAL void duk_push_true(duk_hthread *thr) {
21930 	duk_tval *tv_slot;
21931 
21932 	DUK_ASSERT_API_ENTRY(thr);
21933 	DUK__CHECK_SPACE();
21934 	tv_slot = thr->valstack_top++;
21935 	DUK_TVAL_SET_BOOLEAN_TRUE(tv_slot);
21936 }
21937 
duk_push_false(duk_hthread * thr)21938 DUK_EXTERNAL void duk_push_false(duk_hthread *thr) {
21939 	duk_tval *tv_slot;
21940 
21941 	DUK_ASSERT_API_ENTRY(thr);
21942 	DUK__CHECK_SPACE();
21943 	tv_slot = thr->valstack_top++;
21944 	DUK_TVAL_SET_BOOLEAN_FALSE(tv_slot);
21945 }
21946 
21947 /* normalize NaN which may not match our canonical internal NaN */
duk_push_number(duk_hthread * thr,duk_double_t val)21948 DUK_EXTERNAL void duk_push_number(duk_hthread *thr, duk_double_t val) {
21949 	duk_tval *tv_slot;
21950 	duk_double_union du;
21951 
21952 	DUK_ASSERT_API_ENTRY(thr);
21953 	DUK__CHECK_SPACE();
21954 	du.d = val;
21955 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
21956 	tv_slot = thr->valstack_top++;
21957 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
21958 }
21959 
duk_push_int(duk_hthread * thr,duk_int_t val)21960 DUK_EXTERNAL void duk_push_int(duk_hthread *thr, duk_int_t val) {
21961 #if defined(DUK_USE_FASTINT)
21962 	duk_tval *tv_slot;
21963 
21964 	DUK_ASSERT_API_ENTRY(thr);
21965 	DUK__CHECK_SPACE();
21966 	tv_slot = thr->valstack_top++;
21967 #if DUK_INT_MAX <= 0x7fffffffL
21968 	DUK_TVAL_SET_I32(tv_slot, (duk_int32_t) val);
21969 #else
21970 	if (val >= DUK_FASTINT_MIN && val <= DUK_FASTINT_MAX) {
21971 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
21972 	} else {
21973 		duk_double_t = (duk_double_t) val;
21974 		DUK_TVAL_SET_NUMBER(tv_slot, d);
21975 	}
21976 #endif
21977 #else  /* DUK_USE_FASTINT */
21978 	duk_tval *tv_slot;
21979 	duk_double_t d;
21980 
21981 	DUK_ASSERT_API_ENTRY(thr);
21982 	DUK__CHECK_SPACE();
21983 	d = (duk_double_t) val;
21984 	tv_slot = thr->valstack_top++;
21985 	DUK_TVAL_SET_NUMBER(tv_slot, d);
21986 #endif  /* DUK_USE_FASTINT */
21987 }
21988 
duk_push_uint(duk_hthread * thr,duk_uint_t val)21989 DUK_EXTERNAL void duk_push_uint(duk_hthread *thr, duk_uint_t val) {
21990 #if defined(DUK_USE_FASTINT)
21991 	duk_tval *tv_slot;
21992 
21993 	DUK_ASSERT_API_ENTRY(thr);
21994 	DUK__CHECK_SPACE();
21995 	tv_slot = thr->valstack_top++;
21996 #if DUK_UINT_MAX <= 0xffffffffUL
21997 	DUK_TVAL_SET_U32(tv_slot, (duk_uint32_t) val);
21998 #else
21999 	if (val <= DUK_FASTINT_MAX) {  /* val is unsigned so >= 0 */
22000 		/* XXX: take advantage of val being unsigned, no need to mask */
22001 		DUK_TVAL_SET_FASTINT(tv_slot, (duk_int64_t) val);
22002 	} else {
22003 		duk_double_t = (duk_double_t) val;
22004 		DUK_TVAL_SET_NUMBER(tv_slot, d);
22005 	}
22006 #endif
22007 #else  /* DUK_USE_FASTINT */
22008 	duk_tval *tv_slot;
22009 	duk_double_t d;
22010 
22011 	DUK_ASSERT_API_ENTRY(thr);
22012 	DUK__CHECK_SPACE();
22013 	d = (duk_double_t) val;
22014 	tv_slot = thr->valstack_top++;
22015 	DUK_TVAL_SET_NUMBER(tv_slot, d);
22016 #endif  /* DUK_USE_FASTINT */
22017 }
22018 
duk_push_nan(duk_hthread * thr)22019 DUK_EXTERNAL void duk_push_nan(duk_hthread *thr) {
22020 	duk_tval *tv_slot;
22021 	duk_double_union du;
22022 
22023 	DUK_ASSERT_API_ENTRY(thr);
22024 	DUK__CHECK_SPACE();
22025 	DUK_DBLUNION_SET_NAN(&du);
22026 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
22027 	tv_slot = thr->valstack_top++;
22028 	DUK_TVAL_SET_NUMBER(tv_slot, du.d);
22029 }
22030 
duk_push_lstring(duk_hthread * thr,const char * str,duk_size_t len)22031 DUK_EXTERNAL const char *duk_push_lstring(duk_hthread *thr, const char *str, duk_size_t len) {
22032 	duk_hstring *h;
22033 	duk_tval *tv_slot;
22034 
22035 	DUK_ASSERT_API_ENTRY(thr);
22036 
22037 	/* Check stack before interning (avoid hanging temp). */
22038 	DUK__CHECK_SPACE();
22039 
22040 	/* NULL with zero length represents an empty string; NULL with higher
22041 	 * length is also now treated like an empty string although it is
22042 	 * a bit dubious.  This is unlike duk_push_string() which pushes a
22043 	 * 'null' if the input string is a NULL.
22044 	 */
22045 	if (DUK_UNLIKELY(str == NULL)) {
22046 		len = 0U;
22047 	}
22048 
22049 	/* Check for maximum string length. */
22050 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22051 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22052 		DUK_WO_NORETURN(return NULL;);
22053 	}
22054 
22055 	h = duk_heap_strtable_intern_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22056 	DUK_ASSERT(h != NULL);
22057 
22058 	tv_slot = thr->valstack_top++;
22059 	DUK_TVAL_SET_STRING(tv_slot, h);
22060 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22061 
22062 	return (const char *) DUK_HSTRING_GET_DATA(h);
22063 }
22064 
duk_push_string(duk_hthread * thr,const char * str)22065 DUK_EXTERNAL const char *duk_push_string(duk_hthread *thr, const char *str) {
22066 	DUK_ASSERT_API_ENTRY(thr);
22067 
22068 	if (str) {
22069 		return duk_push_lstring(thr, str, DUK_STRLEN(str));
22070 	} else {
22071 		duk_push_null(thr);
22072 		return NULL;
22073 	}
22074 }
22075 
22076 #if !defined(DUK_USE_PREFER_SIZE)
22077 #if defined(DUK_USE_LITCACHE_SIZE)
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22078 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22079 	duk_hstring *h;
22080 	duk_tval *tv_slot;
22081 
22082 	DUK_ASSERT_API_ENTRY(thr);
22083 	DUK_ASSERT(str != NULL);
22084 	DUK_ASSERT(str[len] == (char) 0);
22085 
22086 	/* Check for maximum string length. */
22087 	if (DUK_UNLIKELY(len > DUK_HSTRING_MAX_BYTELEN)) {
22088 		DUK_ERROR_RANGE(thr, DUK_STR_STRING_TOO_LONG);
22089 		DUK_WO_NORETURN(return NULL;);
22090 	}
22091 
22092 	h = duk_heap_strtable_intern_literal_checked(thr, (const duk_uint8_t *) str, (duk_uint32_t) len);
22093 	DUK_ASSERT(h != NULL);
22094 
22095 	tv_slot = thr->valstack_top++;
22096 	DUK_TVAL_SET_STRING(tv_slot, h);
22097 	DUK_HSTRING_INCREF(thr, h);  /* no side effects */
22098 
22099 	return (const char *) DUK_HSTRING_GET_DATA(h);
22100 }
22101 #else  /* DUK_USE_LITCACHE_SIZE */
duk_push_literal_raw(duk_hthread * thr,const char * str,duk_size_t len)22102 DUK_EXTERNAL const char *duk_push_literal_raw(duk_hthread *thr, const char *str, duk_size_t len) {
22103 	DUK_ASSERT_API_ENTRY(thr);
22104 	DUK_ASSERT(str != NULL);
22105 	DUK_ASSERT(str[len] == (char) 0);
22106 
22107 	return duk_push_lstring(thr, str, len);
22108 }
22109 #endif  /* DUK_USE_LITCACHE_SIZE */
22110 #endif  /* !DUK_USE_PREFER_SIZE */
22111 
duk_push_pointer(duk_hthread * thr,void * val)22112 DUK_EXTERNAL void duk_push_pointer(duk_hthread *thr, void *val) {
22113 	duk_tval *tv_slot;
22114 
22115 	DUK_ASSERT_API_ENTRY(thr);
22116 	DUK__CHECK_SPACE();
22117 	tv_slot = thr->valstack_top++;
22118 	DUK_TVAL_SET_POINTER(tv_slot, val);
22119 }
22120 
duk_push_uint_to_hstring(duk_hthread * thr,duk_uint_t i)22121 DUK_INTERNAL duk_hstring *duk_push_uint_to_hstring(duk_hthread *thr, duk_uint_t i) {
22122 	duk_hstring *h_tmp;
22123 
22124 	DUK_ASSERT_API_ENTRY(thr);
22125 
22126 	/* XXX: this could be a direct DUK_SPRINTF to a buffer followed by duk_push_string() */
22127 	duk_push_uint(thr, (duk_uint_t) i);
22128 	h_tmp = duk_to_hstring_m1(thr);
22129 	DUK_ASSERT(h_tmp != NULL);
22130 	return h_tmp;
22131 }
22132 
duk__push_this_helper(duk_hthread * thr,duk_small_uint_t check_object_coercible)22133 DUK_LOCAL void duk__push_this_helper(duk_hthread *thr, duk_small_uint_t check_object_coercible) {
22134 	duk_tval *tv_slot;
22135 
22136 	DUK__CHECK_SPACE();
22137 
22138 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* because of valstack init policy */
22139 	tv_slot = thr->valstack_top++;
22140 
22141 	if (DUK_UNLIKELY(thr->callstack_curr == NULL)) {
22142 		if (check_object_coercible) {
22143 			goto type_error;
22144 		}
22145 		/* 'undefined' already on stack top */
22146 	} else {
22147 		duk_tval *tv;
22148 
22149 		/* 'this' binding is just before current activation's bottom */
22150 		DUK_ASSERT(thr->valstack_bottom > thr->valstack);
22151 		tv = thr->valstack_bottom - 1;
22152 		if (check_object_coercible &&
22153 		    (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv))) {
22154 			/* XXX: better macro for DUK_TVAL_IS_UNDEFINED_OR_NULL(tv) */
22155 			goto type_error;
22156 		}
22157 
22158 		DUK_TVAL_SET_TVAL(tv_slot, tv);
22159 		DUK_TVAL_INCREF(thr, tv);
22160 	}
22161 	return;
22162 
22163  type_error:
22164 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_OBJECT_COERCIBLE);
22165 	DUK_WO_NORETURN(return;);
22166 }
22167 
duk_push_this(duk_hthread * thr)22168 DUK_EXTERNAL void duk_push_this(duk_hthread *thr) {
22169 	DUK_ASSERT_API_ENTRY(thr);
22170 
22171 	duk__push_this_helper(thr, 0 /*check_object_coercible*/);
22172 }
22173 
duk_push_this_check_object_coercible(duk_hthread * thr)22174 DUK_INTERNAL void duk_push_this_check_object_coercible(duk_hthread *thr) {
22175 	DUK_ASSERT_API_ENTRY(thr);
22176 
22177 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22178 }
22179 
duk_push_this_coercible_to_object(duk_hthread * thr)22180 DUK_INTERNAL duk_hobject *duk_push_this_coercible_to_object(duk_hthread *thr) {
22181 	duk_hobject *h;
22182 
22183 	DUK_ASSERT_API_ENTRY(thr);
22184 
22185 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22186 	h = duk_to_hobject(thr, -1);
22187 	DUK_ASSERT(h != NULL);
22188 	return h;
22189 }
22190 
duk_push_this_coercible_to_string(duk_hthread * thr)22191 DUK_INTERNAL duk_hstring *duk_push_this_coercible_to_string(duk_hthread *thr) {
22192 	DUK_ASSERT_API_ENTRY(thr);
22193 
22194 	duk__push_this_helper(thr, 1 /*check_object_coercible*/);
22195 	return duk_to_hstring_m1(thr);  /* This will reject all Symbol values; accepts Symbol objects. */
22196 }
22197 
duk_get_borrowed_this_tval(duk_hthread * thr)22198 DUK_INTERNAL duk_tval *duk_get_borrowed_this_tval(duk_hthread *thr) {
22199 	DUK_ASSERT_API_ENTRY(thr);
22200 
22201 	DUK_ASSERT(thr->callstack_top > 0);  /* caller required to know */
22202 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller required to know */
22203 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* consequence of above */
22204 	DUK_ASSERT(thr->valstack_bottom - 1 >= thr->valstack);  /* 'this' binding exists */
22205 
22206 	return thr->valstack_bottom - 1;
22207 }
22208 
duk_push_new_target(duk_hthread * thr)22209 DUK_EXTERNAL void duk_push_new_target(duk_hthread *thr) {
22210 	duk_activation *act;
22211 
22212 	DUK_ASSERT_API_ENTRY(thr);
22213 
22214 	/* https://www.ecma-international.org/ecma-262/6.0/#sec-meta-properties-runtime-semantics-evaluation
22215 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-getnewtarget
22216 	 *
22217 	 * No newTarget support now, so as a first approximation
22218 	 * use the resolved (non-bound) target function.
22219 	 *
22220 	 * Check CONSTRUCT flag from current function, or if running
22221 	 * direct eval, from a non-direct-eval parent (with possibly
22222 	 * more than one nested direct eval).  An alternative to this
22223 	 * would be to store [[NewTarget]] as a hidden symbol of the
22224 	 * lexical scope, and then just look up that variable.
22225 	 *
22226 	 * Calls from the application will either be for an empty
22227 	 * call stack, or a Duktape/C function as the top activation.
22228 	 */
22229 
22230 	act = thr->callstack_curr;
22231 	for (;;) {
22232 		if (act == NULL) {
22233 			break;
22234 		}
22235 
22236 		if (act->flags & DUK_ACT_FLAG_CONSTRUCT) {
22237 			duk_push_tval(thr, &act->tv_func);
22238 			return;
22239 		} else if (act->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
22240 			act = act->parent;
22241 		} else {
22242 			break;
22243 		}
22244 	}
22245 
22246 	duk_push_undefined(thr);
22247 }
22248 
duk_push_current_function(duk_hthread * thr)22249 DUK_EXTERNAL void duk_push_current_function(duk_hthread *thr) {
22250 	duk_activation *act;
22251 
22252 	DUK_ASSERT_API_ENTRY(thr);
22253 
22254 	act = thr->callstack_curr;
22255 	if (act != NULL) {
22256 		duk_push_tval(thr, &act->tv_func);
22257 	} else {
22258 		duk_push_undefined(thr);
22259 	}
22260 }
22261 
duk_push_current_thread(duk_hthread * thr)22262 DUK_EXTERNAL void duk_push_current_thread(duk_hthread *thr) {
22263 	DUK_ASSERT_API_ENTRY(thr);
22264 
22265 	if (thr->heap->curr_thread) {
22266 		duk_push_hobject(thr, (duk_hobject *) thr->heap->curr_thread);
22267 	} else {
22268 		duk_push_undefined(thr);
22269 	}
22270 }
22271 
duk_push_global_object(duk_hthread * thr)22272 DUK_EXTERNAL void duk_push_global_object(duk_hthread *thr) {
22273 	DUK_ASSERT_API_ENTRY(thr);
22274 
22275 	duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
22276 }
22277 
22278 /* XXX: size optimize */
duk__push_stash(duk_hthread * thr)22279 DUK_LOCAL void duk__push_stash(duk_hthread *thr) {
22280 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE)) {
22281 		DUK_DDD(DUK_DDDPRINT("creating heap/global/thread stash on first use"));
22282 		duk_pop_unsafe(thr);
22283 		duk_push_bare_object(thr);
22284 		duk_dup_top(thr);
22285 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_C);  /* [ ... parent stash stash ] -> [ ... parent stash ] */
22286 	}
22287 	duk_remove_m2(thr);
22288 }
22289 
duk_push_heap_stash(duk_hthread * thr)22290 DUK_EXTERNAL void duk_push_heap_stash(duk_hthread *thr) {
22291 	duk_heap *heap;
22292 	DUK_ASSERT_API_ENTRY(thr);
22293 	heap = thr->heap;
22294 	DUK_ASSERT(heap->heap_object != NULL);
22295 	duk_push_hobject(thr, heap->heap_object);
22296 	duk__push_stash(thr);
22297 }
22298 
duk_push_global_stash(duk_hthread * thr)22299 DUK_EXTERNAL void duk_push_global_stash(duk_hthread *thr) {
22300 	DUK_ASSERT_API_ENTRY(thr);
22301 	duk_push_global_object(thr);
22302 	duk__push_stash(thr);
22303 }
22304 
duk_push_thread_stash(duk_hthread * thr,duk_hthread * target_thr)22305 DUK_EXTERNAL void duk_push_thread_stash(duk_hthread *thr, duk_hthread *target_thr) {
22306 	DUK_ASSERT_API_ENTRY(thr);
22307 	if (DUK_UNLIKELY(target_thr == NULL)) {
22308 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
22309 		DUK_WO_NORETURN(return;);
22310 	}
22311 	duk_push_hobject(thr, (duk_hobject *) target_thr);
22312 	duk__push_stash(thr);
22313 }
22314 
22315 /* 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)22316 DUK_LOCAL duk_int_t duk__try_push_vsprintf(duk_hthread *thr, void *buf, duk_size_t sz, const char *fmt, va_list ap) {
22317 	duk_int_t len;
22318 
22319 	DUK_ASSERT_CTX_VALID(thr);
22320 	DUK_UNREF(thr);
22321 
22322 	/* NUL terminator handling doesn't matter here */
22323 	len = DUK_VSNPRINTF((char *) buf, sz, fmt, ap);
22324 	if (len < (duk_int_t) sz) {
22325 		/* Return value of 'sz' or more indicates output was (potentially)
22326 		 * truncated.
22327 		 */
22328 		return (duk_int_t) len;
22329 	}
22330 	return -1;
22331 }
22332 
duk_push_vsprintf(duk_hthread * thr,const char * fmt,va_list ap)22333 DUK_EXTERNAL const char *duk_push_vsprintf(duk_hthread *thr, const char *fmt, va_list ap) {
22334 	duk_uint8_t stack_buf[DUK_PUSH_SPRINTF_INITIAL_SIZE];
22335 	duk_size_t sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22336 	duk_bool_t pushed_buf = 0;
22337 	void *buf;
22338 	duk_int_t len;  /* XXX: duk_ssize_t */
22339 	const char *res;
22340 
22341 	DUK_ASSERT_API_ENTRY(thr);
22342 
22343 	/* special handling of fmt==NULL */
22344 	if (!fmt) {
22345 		duk_hstring *h_str;
22346 		duk_push_hstring_empty(thr);
22347 		h_str = duk_known_hstring(thr, -1);
22348 		return (const char *) DUK_HSTRING_GET_DATA(h_str);
22349 	}
22350 
22351 	/* initial estimate based on format string */
22352 	sz = DUK_STRLEN(fmt) + 16;  /* format plus something to avoid just missing */
22353 	if (sz < DUK_PUSH_SPRINTF_INITIAL_SIZE) {
22354 		sz = DUK_PUSH_SPRINTF_INITIAL_SIZE;
22355 	}
22356 	DUK_ASSERT(sz > 0);
22357 
22358 	/* Try to make do with a stack buffer to avoid allocating a temporary buffer.
22359 	 * This works 99% of the time which is quite nice.
22360 	 */
22361 	for (;;) {
22362 		va_list ap_copy;  /* copied so that 'ap' can be reused */
22363 
22364 		if (sz <= sizeof(stack_buf)) {
22365 			buf = stack_buf;
22366 		} else if (!pushed_buf) {
22367 			pushed_buf = 1;
22368 			buf = duk_push_dynamic_buffer(thr, sz);
22369 		} else {
22370 			buf = duk_resize_buffer(thr, -1, sz);
22371 		}
22372 		DUK_ASSERT(buf != NULL);
22373 
22374 		DUK_VA_COPY(ap_copy, ap);
22375 		len = duk__try_push_vsprintf(thr, buf, sz, fmt, ap_copy);
22376 		va_end(ap_copy);
22377 		if (len >= 0) {
22378 			break;
22379 		}
22380 
22381 		/* failed, resize and try again */
22382 		sz = sz * 2;
22383 		if (DUK_UNLIKELY(sz >= DUK_PUSH_SPRINTF_SANITY_LIMIT)) {
22384 			DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
22385 			DUK_WO_NORETURN(return NULL;);
22386 		}
22387 	}
22388 
22389 	/* Cannot use duk_buffer_to_string() on the buffer because it is
22390 	 * usually larger than 'len'; 'buf' is also usually a stack buffer.
22391 	 */
22392 	res = duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);  /* [ buf? res ] */
22393 	if (pushed_buf) {
22394 		duk_remove_m2(thr);
22395 	}
22396 	return res;
22397 }
22398 
duk_push_sprintf(duk_hthread * thr,const char * fmt,...)22399 DUK_EXTERNAL const char *duk_push_sprintf(duk_hthread *thr, const char *fmt, ...) {
22400 	va_list ap;
22401 	const char *ret;
22402 
22403 	DUK_ASSERT_API_ENTRY(thr);
22404 
22405 	/* allow fmt==NULL */
22406 	va_start(ap, fmt);
22407 	ret = duk_push_vsprintf(thr, fmt, ap);
22408 	va_end(ap);
22409 
22410 	return ret;
22411 }
22412 
duk_push_object_helper(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_small_int_t prototype_bidx)22413 DUK_INTERNAL duk_hobject *duk_push_object_helper(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22414 	duk_tval *tv_slot;
22415 	duk_hobject *h;
22416 
22417 	DUK_ASSERT_API_ENTRY(thr);
22418 	DUK_ASSERT(prototype_bidx == -1 ||
22419 	           (prototype_bidx >= 0 && prototype_bidx < DUK_NUM_BUILTINS));
22420 
22421 	DUK__CHECK_SPACE();
22422 
22423 	h = duk_hobject_alloc(thr, hobject_flags_and_class);
22424 	DUK_ASSERT(h != NULL);
22425 
22426 	DUK_DDD(DUK_DDDPRINT("created object with flags: 0x%08lx", (unsigned long) h->hdr.h_flags));
22427 
22428 	tv_slot = thr->valstack_top;
22429 	DUK_TVAL_SET_OBJECT(tv_slot, h);
22430 	DUK_HOBJECT_INCREF(thr, h);  /* no side effects */
22431 	thr->valstack_top++;
22432 
22433 	/* object is now reachable */
22434 
22435 	if (prototype_bidx >= 0) {
22436 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, thr->builtins[prototype_bidx]);
22437 	} else {
22438 		DUK_ASSERT(prototype_bidx == -1);
22439 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h) == NULL);
22440 	}
22441 
22442 	return h;
22443 }
22444 
duk_push_object_helper_proto(duk_hthread * thr,duk_uint_t hobject_flags_and_class,duk_hobject * proto)22445 DUK_INTERNAL duk_hobject *duk_push_object_helper_proto(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_hobject *proto) {
22446 	duk_hobject *h;
22447 
22448 	DUK_ASSERT_API_ENTRY(thr);
22449 
22450 	h = duk_push_object_helper(thr, hobject_flags_and_class, -1);
22451 	DUK_ASSERT(h != NULL);
22452 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, h, proto);
22453 	return h;
22454 }
22455 
duk_push_object(duk_hthread * thr)22456 DUK_EXTERNAL duk_idx_t duk_push_object(duk_hthread *thr) {
22457 	DUK_ASSERT_API_ENTRY(thr);
22458 
22459 	(void) duk_push_object_helper(thr,
22460 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
22461 	                              DUK_HOBJECT_FLAG_FASTREFS |
22462 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
22463 	                              DUK_BIDX_OBJECT_PROTOTYPE);
22464 	return duk_get_top_index_unsafe(thr);
22465 }
22466 
duk_push_array(duk_hthread * thr)22467 DUK_EXTERNAL duk_idx_t duk_push_array(duk_hthread *thr) {
22468 	duk_uint_t flags;
22469 	duk_harray *obj;
22470 	duk_idx_t ret;
22471 	duk_tval *tv_slot;
22472 
22473 	DUK_ASSERT_API_ENTRY(thr);
22474 
22475 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22476 	        DUK_HOBJECT_FLAG_FASTREFS |
22477 	        DUK_HOBJECT_FLAG_ARRAY_PART |
22478 	        DUK_HOBJECT_FLAG_EXOTIC_ARRAY |
22479 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAY);
22480 
22481 	obj = duk_harray_alloc(thr, flags);
22482 	DUK_ASSERT(obj != NULL);
22483 
22484 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_ARRAY_PROTOTYPE]);
22485 
22486 	tv_slot = thr->valstack_top;
22487 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22488 	DUK_HOBJECT_INCREF(thr, obj);  /* XXX: could preallocate with refcount = 1 */
22489 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22490 	thr->valstack_top++;
22491 
22492 	DUK_ASSERT(obj->length == 0);  /* Array .length starts at zero. */
22493 	return ret;
22494 }
22495 
duk_push_harray(duk_hthread * thr)22496 DUK_INTERNAL duk_harray *duk_push_harray(duk_hthread *thr) {
22497 	/* XXX: API call could do this directly, cast to void in API macro. */
22498 	duk_harray *a;
22499 
22500 	DUK_ASSERT_API_ENTRY(thr);
22501 
22502 	(void) duk_push_array(thr);
22503 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(thr->valstack_top - 1));
22504 	a = (duk_harray *) DUK_TVAL_GET_OBJECT(thr->valstack_top - 1);
22505 	DUK_ASSERT(a != NULL);
22506 	return a;
22507 }
22508 
22509 /* Push a duk_harray with preallocated size (.length also set to match size).
22510  * Caller may then populate array part of the duk_harray directly.
22511  */
duk_push_harray_with_size(duk_hthread * thr,duk_uint32_t size)22512 DUK_INTERNAL duk_harray *duk_push_harray_with_size(duk_hthread *thr, duk_uint32_t size) {
22513 	duk_harray *a;
22514 
22515 	DUK_ASSERT_API_ENTRY(thr);
22516 
22517 	a = duk_push_harray(thr);
22518 
22519 	duk_hobject_realloc_props(thr,
22520 	                          (duk_hobject *) a,
22521 	                          0,
22522 	                          size,
22523 	                          0,
22524 	                          0);
22525 	a->length = size;
22526 	return a;
22527 }
22528 
duk_push_harray_with_size_outptr(duk_hthread * thr,duk_uint32_t size)22529 DUK_INTERNAL duk_tval *duk_push_harray_with_size_outptr(duk_hthread *thr, duk_uint32_t size) {
22530 	duk_harray *a;
22531 
22532 	DUK_ASSERT_API_ENTRY(thr);
22533 
22534 	a = duk_push_harray_with_size(thr, size);
22535 	DUK_ASSERT(a != NULL);
22536 	return DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a);
22537 }
22538 
duk_push_thread_raw(duk_hthread * thr,duk_uint_t flags)22539 DUK_EXTERNAL duk_idx_t duk_push_thread_raw(duk_hthread *thr, duk_uint_t flags) {
22540 	duk_hthread *obj;
22541 	duk_idx_t ret;
22542 	duk_tval *tv_slot;
22543 
22544 	DUK_ASSERT_API_ENTRY(thr);
22545 
22546 	DUK__CHECK_SPACE();
22547 
22548 	obj = duk_hthread_alloc(thr,
22549 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
22550 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
22551 	DUK_ASSERT(obj != NULL);
22552 	obj->state = DUK_HTHREAD_STATE_INACTIVE;
22553 #if defined(DUK_USE_ROM_STRINGS)
22554 	/* Nothing to initialize, strs[] is in ROM. */
22555 #else
22556 #if defined(DUK_USE_HEAPPTR16)
22557 	obj->strs16 = thr->strs16;
22558 #else
22559 	obj->strs = thr->strs;
22560 #endif
22561 #endif
22562 	DUK_DDD(DUK_DDDPRINT("created thread object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22563 
22564 	/* make the new thread reachable */
22565 	tv_slot = thr->valstack_top;
22566 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22567 	DUK_HTHREAD_INCREF(thr, obj);
22568 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22569 	thr->valstack_top++;
22570 
22571 	/* important to do this *after* pushing, to make the thread reachable for gc */
22572 	if (DUK_UNLIKELY(!duk_hthread_init_stacks(thr->heap, obj))) {
22573 		DUK_ERROR_ALLOC_FAILED(thr);
22574 		DUK_WO_NORETURN(return 0;);
22575 	}
22576 
22577 	/* initialize built-ins - either by copying or creating new ones */
22578 	if (flags & DUK_THREAD_NEW_GLOBAL_ENV) {
22579 		duk_hthread_create_builtin_objects(obj);
22580 	} else {
22581 		duk_hthread_copy_builtin_objects(thr, obj);
22582 	}
22583 
22584 	/* default prototype */
22585 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, obj->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
22586 
22587 	/* Initial stack size satisfies the stack slack constraints so there
22588 	 * is no need to require stack here.
22589 	 */
22590 	DUK_ASSERT(DUK_VALSTACK_INITIAL_SIZE >=
22591 	           DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
22592 
22593 	return ret;
22594 }
22595 
duk_push_hcompfunc(duk_hthread * thr)22596 DUK_INTERNAL duk_hcompfunc *duk_push_hcompfunc(duk_hthread *thr) {
22597 	duk_hcompfunc *obj;
22598 	duk_tval *tv_slot;
22599 
22600 	DUK_ASSERT_API_ENTRY(thr);
22601 
22602 	DUK__CHECK_SPACE();
22603 
22604 	/* Template functions are not strictly constructable (they don't
22605 	 * have a "prototype" property for instance), so leave the
22606 	 * DUK_HOBJECT_FLAG_CONSRUCTABLE flag cleared here.
22607 	 */
22608 
22609 	obj = duk_hcompfunc_alloc(thr,
22610 	                          DUK_HOBJECT_FLAG_EXTENSIBLE |
22611 	                          DUK_HOBJECT_FLAG_CALLABLE |
22612 	                          DUK_HOBJECT_FLAG_COMPFUNC |
22613 	                          DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22614 	if (DUK_UNLIKELY(obj == NULL)) {
22615 		DUK_ERROR_ALLOC_FAILED(thr);
22616 		DUK_WO_NORETURN(return NULL;);
22617 	}
22618 
22619 	DUK_DDD(DUK_DDDPRINT("created compiled function object with flags: 0x%08lx", (unsigned long) obj->obj.hdr.h_flags));
22620 
22621 	tv_slot = thr->valstack_top;
22622 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22623 	DUK_HOBJECT_INCREF(thr, obj);
22624 	thr->valstack_top++;
22625 
22626 	/* default prototype */
22627 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22628 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
22629 
22630 	return obj;
22631 }
22632 
duk_push_hboundfunc(duk_hthread * thr)22633 DUK_INTERNAL duk_hboundfunc *duk_push_hboundfunc(duk_hthread *thr) {
22634 	duk_hboundfunc *obj;
22635 	duk_tval *tv_slot;
22636 
22637 	DUK_ASSERT_API_ENTRY(thr);
22638 
22639 	DUK__CHECK_SPACE();
22640 	obj = duk_hboundfunc_alloc(thr->heap,
22641 	                           DUK_HOBJECT_FLAG_EXTENSIBLE |
22642 	                           DUK_HOBJECT_FLAG_BOUNDFUNC |
22643 	                           DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22644 	                           DUK_HOBJECT_FLAG_CALLABLE |
22645 	                           DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION));
22646 	if (!obj) {
22647 		DUK_ERROR_ALLOC_FAILED(thr);
22648 		DUK_WO_NORETURN(return NULL;);
22649 	}
22650 
22651 	tv_slot = thr->valstack_top++;
22652 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22653 	DUK_HOBJECT_INCREF(thr, obj);
22654 
22655 	/* Prototype is left as NULL because the caller always sets it (and
22656 	 * it depends on the target function).
22657 	 */
22658 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) obj) == NULL);
22659 
22660 	return obj;
22661 }
22662 
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)22663 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) {
22664 	duk_hnatfunc *obj;
22665 	duk_idx_t ret;
22666 	duk_tval *tv_slot;
22667 	duk_int16_t func_nargs;
22668 
22669 	DUK_ASSERT_CTX_VALID(thr);
22670 
22671 	DUK__CHECK_SPACE();
22672 
22673 	if (DUK_UNLIKELY(func == NULL)) {
22674 		goto api_error;
22675 	}
22676 	if (nargs >= 0 && nargs < DUK_HNATFUNC_NARGS_MAX) {
22677 		func_nargs = (duk_int16_t) nargs;
22678 	} else if (nargs == DUK_VARARGS) {
22679 		func_nargs = DUK_HNATFUNC_NARGS_VARARGS;
22680 	} else {
22681 		goto api_error;
22682 	}
22683 
22684 	obj = duk_hnatfunc_alloc(thr, flags);
22685 	DUK_ASSERT(obj != NULL);
22686 
22687 	obj->func = func;
22688 	obj->nargs = func_nargs;
22689 
22690 	DUK_DDD(DUK_DDDPRINT("created native function object with flags: 0x%08lx, nargs=%ld",
22691 	                     (unsigned long) obj->obj.hdr.h_flags, (long) obj->nargs));
22692 
22693 	tv_slot = thr->valstack_top;
22694 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22695 	DUK_HOBJECT_INCREF(thr, obj);
22696 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
22697 	thr->valstack_top++;
22698 
22699 	DUK_ASSERT_BIDX_VALID(proto_bidx);
22700 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[proto_bidx]);
22701 	return ret;
22702 
22703  api_error:
22704 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22705 	DUK_WO_NORETURN(return 0;);
22706 }
22707 
duk_push_c_function(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22708 DUK_EXTERNAL duk_idx_t duk_push_c_function(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22709 	duk_uint_t flags;
22710 
22711 	DUK_ASSERT_API_ENTRY(thr);
22712 
22713 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22714 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22715 	        DUK_HOBJECT_FLAG_CALLABLE |
22716 	        DUK_HOBJECT_FLAG_FASTREFS |
22717 	        DUK_HOBJECT_FLAG_NATFUNC |
22718 	        DUK_HOBJECT_FLAG_NEWENV |
22719 	        DUK_HOBJECT_FLAG_STRICT |
22720 	        DUK_HOBJECT_FLAG_NOTAIL |
22721 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22722 
22723 	/* Default prototype is a Duktape specific %NativeFunctionPrototype%
22724 	 * which provides .length and .name getters.
22725 	 */
22726 	return duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE);
22727 }
22728 
duk_push_c_function_builtin(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22729 DUK_INTERNAL void duk_push_c_function_builtin(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22730 	duk_uint_t flags;
22731 
22732 	DUK_ASSERT_API_ENTRY(thr);
22733 
22734 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22735 	        DUK_HOBJECT_FLAG_CONSTRUCTABLE |
22736 	        DUK_HOBJECT_FLAG_CALLABLE |
22737 	        DUK_HOBJECT_FLAG_FASTREFS |
22738 	        DUK_HOBJECT_FLAG_NATFUNC |
22739 	        DUK_HOBJECT_FLAG_NEWENV |
22740 	        DUK_HOBJECT_FLAG_STRICT |
22741 	        DUK_HOBJECT_FLAG_NOTAIL |
22742 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22743 
22744 	/* Must use Function.prototype for standard built-in functions. */
22745 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22746 }
22747 
duk_push_c_function_builtin_noconstruct(duk_hthread * thr,duk_c_function func,duk_int_t nargs)22748 DUK_INTERNAL void duk_push_c_function_builtin_noconstruct(duk_hthread *thr, duk_c_function func, duk_int_t nargs) {
22749 	duk_uint_t flags;
22750 
22751 	DUK_ASSERT_API_ENTRY(thr);
22752 
22753 	flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
22754 	        DUK_HOBJECT_FLAG_CALLABLE |
22755 	        DUK_HOBJECT_FLAG_FASTREFS |
22756 	        DUK_HOBJECT_FLAG_NATFUNC |
22757 	        DUK_HOBJECT_FLAG_NEWENV |
22758 	        DUK_HOBJECT_FLAG_STRICT |
22759 	        DUK_HOBJECT_FLAG_NOTAIL |
22760 	        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION);
22761 
22762 	/* Must use Function.prototype for standard built-in functions. */
22763 	(void) duk__push_c_function_raw(thr, func, nargs, flags, DUK_BIDX_FUNCTION_PROTOTYPE);
22764 }
22765 
duk_push_c_lightfunc(duk_hthread * thr,duk_c_function func,duk_idx_t nargs,duk_idx_t length,duk_int_t magic)22766 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) {
22767 	duk_small_uint_t lf_flags;
22768 	duk_tval *tv_slot;
22769 
22770 	DUK_ASSERT_API_ENTRY(thr);
22771 
22772 	DUK__CHECK_SPACE();
22773 
22774 	if (nargs >= DUK_LFUNC_NARGS_MIN && nargs <= DUK_LFUNC_NARGS_MAX) {
22775 		/* as is */
22776 	} else if (nargs == DUK_VARARGS) {
22777 		nargs = DUK_LFUNC_NARGS_VARARGS;
22778 	} else {
22779 		goto api_error;
22780 	}
22781 	if (DUK_UNLIKELY(!(length >= DUK_LFUNC_LENGTH_MIN && length <= DUK_LFUNC_LENGTH_MAX))) {
22782 		goto api_error;
22783 	}
22784 	if (DUK_UNLIKELY(!(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX))) {
22785 		goto api_error;
22786 	}
22787 
22788 	lf_flags = DUK_LFUNC_FLAGS_PACK((duk_small_int_t) magic, (duk_small_uint_t) length, (duk_small_uint_t) nargs);
22789 	tv_slot = thr->valstack_top++;
22790 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_slot));
22791 	DUK_TVAL_SET_LIGHTFUNC(tv_slot, func, lf_flags);
22792 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
22793 	return (duk_idx_t) (tv_slot - thr->valstack_bottom);
22794 
22795  api_error:
22796 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
22797 	DUK_WO_NORETURN(return 0;);
22798 }
22799 
22800 #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)22801 DUK_INTERNAL duk_hbufobj *duk_push_bufobj_raw(duk_hthread *thr, duk_uint_t hobject_flags_and_class, duk_small_int_t prototype_bidx) {
22802 	duk_hbufobj *obj;
22803 	duk_tval *tv_slot;
22804 
22805 	DUK_ASSERT_API_ENTRY(thr);
22806 	DUK_ASSERT(prototype_bidx >= 0);
22807 
22808 	DUK__CHECK_SPACE();
22809 
22810 	obj = duk_hbufobj_alloc(thr, hobject_flags_and_class);
22811 	DUK_ASSERT(obj != NULL);
22812 
22813 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) obj, thr->builtins[prototype_bidx]);
22814 	DUK_ASSERT_HBUFOBJ_VALID(obj);
22815 
22816 	tv_slot = thr->valstack_top;
22817 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) obj);
22818 	DUK_HOBJECT_INCREF(thr, obj);
22819 	thr->valstack_top++;
22820 
22821 	return obj;
22822 }
22823 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22824 
22825 /* XXX: There's quite a bit of overlap with buffer creation handling in
22826  * duk_bi_buffer.c.  Look for overlap and refactor.
22827  */
22828 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
22829 #define DUK__PACK_ARGS(classnum,protobidx,elemtype,elemshift,istypedarray) \
22830 	(((classnum) << 24) | ((protobidx) << 16) | ((elemtype) << 8) | ((elemshift) << 4) | (istypedarray))
22831 
22832 static const duk_uint32_t duk__bufobj_flags_lookup[] = {
22833 	/* Node.js Buffers are Uint8Array instances which inherit from Buffer.prototype. */
22834 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_ARRAYBUFFER,       DUK_BIDX_ARRAYBUFFER_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_ARRAYBUFFER */
22835 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_NODEJS_BUFFER_PROTOTYPE,     DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_NODEJS_BUFFER */
22836 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_DATAVIEW,          DUK_BIDX_DATAVIEW_PROTOTYPE,          DUK_HBUFOBJ_ELEM_UINT8,        0, 0),  /* DUK_BUFOBJ_DATAVIEW */
22837 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT8ARRAY,         DUK_BIDX_INT8ARRAY_PROTOTYPE,         DUK_HBUFOBJ_ELEM_INT8,         0, 1),  /* DUK_BUFOBJ_INT8ARRAY */
22838 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8ARRAY,        DUK_BIDX_UINT8ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_UINT8,        0, 1),  /* DUK_BUFOBJ_UINT8ARRAY */
22839 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY, DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE, DUK_HBUFOBJ_ELEM_UINT8CLAMPED, 0, 1),  /* DUK_BUFOBJ_UINT8CLAMPEDARRAY */
22840 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT16ARRAY,        DUK_BIDX_INT16ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT16,        1, 1),  /* DUK_BUFOBJ_INT16ARRAY */
22841 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT16ARRAY,       DUK_BIDX_UINT16ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT16,       1, 1),  /* DUK_BUFOBJ_UINT16ARRAY */
22842 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_INT32ARRAY,        DUK_BIDX_INT32ARRAY_PROTOTYPE,        DUK_HBUFOBJ_ELEM_INT32,        2, 1),  /* DUK_BUFOBJ_INT32ARRAY */
22843 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_UINT32ARRAY,       DUK_BIDX_UINT32ARRAY_PROTOTYPE,       DUK_HBUFOBJ_ELEM_UINT32,       2, 1),  /* DUK_BUFOBJ_UINT32ARRAY */
22844 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT32ARRAY,      DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT32,      2, 1),  /* DUK_BUFOBJ_FLOAT32ARRAY */
22845 	DUK__PACK_ARGS(DUK_HOBJECT_CLASS_FLOAT64ARRAY,      DUK_BIDX_FLOAT64ARRAY_PROTOTYPE,      DUK_HBUFOBJ_ELEM_FLOAT64,      3, 1)   /* DUK_BUFOBJ_FLOAT64ARRAY */
22846 };
22847 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22848 
22849 #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)22850 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) {
22851 	duk_hbufobj *h_bufobj;
22852 	duk_hbuffer *h_val;
22853 	duk_hobject *h_arraybuf;
22854 	duk_uint32_t tmp;
22855 	duk_uint_t classnum;
22856 	duk_uint_t protobidx;
22857 	duk_uint_t lookupidx;
22858 	duk_uint_t uint_offset, uint_length, uint_added;
22859 
22860 	DUK_ASSERT_API_ENTRY(thr);
22861 
22862 	/* The underlying types for offset/length in duk_hbufobj is
22863 	 * duk_uint_t; make sure argument values fit.
22864 	 */
22865 	uint_offset = (duk_uint_t) byte_offset;
22866 	uint_length = (duk_uint_t) byte_length;
22867 	if (sizeof(duk_size_t) != sizeof(duk_uint_t)) {
22868 		if (DUK_UNLIKELY((duk_size_t) uint_offset != byte_offset || (duk_size_t) uint_length != byte_length)) {
22869 			goto range_error;
22870 		}
22871 	}
22872 
22873 	DUK_ASSERT_DISABLE(flags >= 0);  /* flags is unsigned */
22874 	lookupidx = flags;
22875 	if (DUK_UNLIKELY(lookupidx >= sizeof(duk__bufobj_flags_lookup) / sizeof(duk_uint32_t))) {
22876 		goto arg_error;
22877 	}
22878 	tmp = duk__bufobj_flags_lookup[lookupidx];
22879 	classnum = tmp >> 24;
22880 	protobidx = (tmp >> 16) & 0xff;
22881 
22882 	h_arraybuf = duk_get_hobject(thr, idx_buffer);
22883 	if (h_arraybuf != NULL &&  /* argument is an object */
22884 	    flags != DUK_BUFOBJ_ARRAYBUFFER &&  /* creating a view */
22885 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_arraybuf) == DUK_HOBJECT_CLASS_ARRAYBUFFER  /* argument is ArrayBuffer */) {
22886 		duk_uint_t tmp_offset;
22887 
22888 		DUK_ASSERT_HBUFOBJ_VALID((duk_hbufobj *) h_arraybuf);
22889 		h_val = ((duk_hbufobj *) h_arraybuf)->buf;
22890 		if (DUK_UNLIKELY(h_val == NULL)) {
22891 			goto arg_error;
22892 		}
22893 
22894 		tmp_offset = uint_offset + ((duk_hbufobj *) h_arraybuf)->offset;
22895 		if (DUK_UNLIKELY(tmp_offset < uint_offset)) {
22896 			goto range_error;
22897 		}
22898 		uint_offset = tmp_offset;
22899 
22900 		/* Note intentional difference to new TypedArray(): we allow
22901 		 * caller to create an uncovered typed array (which is memory
22902 		 * safe); new TypedArray() rejects it.
22903 		 */
22904 	} else {
22905 		/* Handle unexpected object arguments here too, for nice error
22906 		 * messages.
22907 		 */
22908 		h_arraybuf = NULL;
22909 		h_val = duk_require_hbuffer(thr, idx_buffer);
22910 	}
22911 
22912 	/* Wrap check for offset+length. */
22913 	uint_added = uint_offset + uint_length;
22914 	if (DUK_UNLIKELY(uint_added < uint_offset)) {
22915 		goto range_error;
22916 	}
22917 	DUK_ASSERT(uint_added >= uint_offset && uint_added >= uint_length);
22918 
22919 	DUK_ASSERT(h_val != NULL);
22920 
22921 	h_bufobj = duk_push_bufobj_raw(thr,
22922 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
22923 	                               DUK_HOBJECT_FLAG_BUFOBJ |
22924 	                               DUK_HOBJECT_CLASS_AS_FLAGS(classnum),
22925 	                               (duk_small_int_t) protobidx);
22926 	DUK_ASSERT(h_bufobj != NULL);
22927 
22928 	h_bufobj->buf = h_val;
22929 	DUK_HBUFFER_INCREF(thr, h_val);
22930 	h_bufobj->buf_prop = h_arraybuf;
22931 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, h_arraybuf);
22932 	h_bufobj->offset = uint_offset;
22933 	h_bufobj->length = uint_length;
22934 	h_bufobj->shift = (tmp >> 4) & 0x0f;
22935 	h_bufobj->elem_type = (tmp >> 8) & 0xff;
22936 	h_bufobj->is_typedarray = tmp & 0x0f;
22937 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
22938 
22939 	/* TypedArray views need an automatic ArrayBuffer which must be
22940 	 * provided as .buffer property of the view.  The ArrayBuffer is
22941 	 * referenced via duk_hbufobj->buf_prop and an inherited .buffer
22942 	 * accessor returns it.  The ArrayBuffer is created lazily on first
22943 	 * access if necessary so we don't need to do anything more here.
22944 	 */
22945 	return;
22946 
22947  range_error:
22948 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
22949 	DUK_WO_NORETURN(return;);
22950 
22951  arg_error:
22952 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_ARGS);
22953 	DUK_WO_NORETURN(return;);
22954 }
22955 #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)22956 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) {
22957 	DUK_ASSERT_API_ENTRY(thr);
22958 	DUK_UNREF(idx_buffer);
22959 	DUK_UNREF(byte_offset);
22960 	DUK_UNREF(byte_length);
22961 	DUK_UNREF(flags);
22962 	DUK_ERROR_UNSUPPORTED(thr);
22963 	DUK_WO_NORETURN(return;);
22964 }
22965 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
22966 
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)22967 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) {
22968 	duk_hobject *proto;
22969 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
22970 	duk_small_uint_t augment_flags;
22971 #endif
22972 
22973 	DUK_ASSERT_API_ENTRY(thr);
22974 	DUK_ASSERT(thr != NULL);
22975 	DUK_UNREF(filename);
22976 	DUK_UNREF(line);
22977 
22978 	/* Error code also packs a tracedata related flag. */
22979 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
22980 	augment_flags = 0;
22981 	if (err_code & DUK_ERRCODE_FLAG_NOBLAME_FILELINE) {
22982 		augment_flags = DUK_AUGMENT_FLAG_NOBLAME_FILELINE;
22983 	}
22984 #endif
22985 	err_code = err_code & (~DUK_ERRCODE_FLAG_NOBLAME_FILELINE);
22986 
22987 	/* error gets its 'name' from the prototype */
22988 	proto = duk_error_prototype_from_code(thr, err_code);
22989 	(void) duk_push_object_helper_proto(thr,
22990 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
22991 	                                    DUK_HOBJECT_FLAG_FASTREFS |
22992 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR),
22993 	                                    proto);
22994 
22995 	/* ... and its 'message' from an instance property */
22996 	if (fmt) {
22997 		duk_push_vsprintf(thr, fmt, ap);
22998 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
22999 	} else {
23000 		/* If no explicit message given, put error code into message field
23001 		 * (as a number).  This is not fully in keeping with the ECMAScript
23002 		 * error model because messages are supposed to be strings (Error
23003 		 * constructors use ToString() on their argument).  However, it's
23004 		 * probably more useful than having a separate 'code' property.
23005 		 */
23006 		duk_push_int(thr, err_code);
23007 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
23008 	}
23009 
23010 	/* XXX: .code = err_code disabled, not sure if useful */
23011 
23012 	/* Creation time error augmentation */
23013 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
23014 	/* filename may be NULL in which case file/line is not recorded */
23015 	duk_err_augment_error_create(thr, thr, filename, line, augment_flags);  /* may throw an error */
23016 #endif
23017 
23018 	return duk_get_top_index_unsafe(thr);
23019 }
23020 
duk_push_error_object_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23021 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, ...) {
23022 	va_list ap;
23023 	duk_idx_t ret;
23024 
23025 	DUK_ASSERT_API_ENTRY(thr);
23026 
23027 	va_start(ap, fmt);
23028 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23029 	va_end(ap);
23030 	return ret;
23031 }
23032 
23033 #if !defined(DUK_USE_VARIADIC_MACROS)
duk_push_error_object_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23034 DUK_EXTERNAL duk_idx_t duk_push_error_object_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23035 	const char *filename = duk_api_global_filename;
23036 	duk_int_t line = duk_api_global_line;
23037 	va_list ap;
23038 	duk_idx_t ret;
23039 
23040 	DUK_ASSERT_API_ENTRY(thr);
23041 
23042 	duk_api_global_filename = NULL;
23043 	duk_api_global_line = 0;
23044 	va_start(ap, fmt);
23045 	ret = duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23046 	va_end(ap);
23047 	return ret;
23048 }
23049 #endif  /* DUK_USE_VARIADIC_MACROS */
23050 
duk_push_buffer_raw(duk_hthread * thr,duk_size_t size,duk_small_uint_t flags)23051 DUK_EXTERNAL void *duk_push_buffer_raw(duk_hthread *thr, duk_size_t size, duk_small_uint_t flags) {
23052 	duk_tval *tv_slot;
23053 	duk_hbuffer *h;
23054 	void *buf_data;
23055 
23056 	DUK_ASSERT_API_ENTRY(thr);
23057 
23058 	DUK__CHECK_SPACE();
23059 
23060 	/* Check for maximum buffer length. */
23061 	if (DUK_UNLIKELY(size > DUK_HBUFFER_MAX_BYTELEN)) {
23062 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
23063 		DUK_WO_NORETURN(return NULL;);
23064 	}
23065 
23066 	h = duk_hbuffer_alloc(thr->heap, size, flags, &buf_data);
23067 	if (DUK_UNLIKELY(h == NULL)) {
23068 		DUK_ERROR_ALLOC_FAILED(thr);
23069 		DUK_WO_NORETURN(return NULL;);
23070 	}
23071 
23072 	tv_slot = thr->valstack_top;
23073 	DUK_TVAL_SET_BUFFER(tv_slot, h);
23074 	DUK_HBUFFER_INCREF(thr, h);
23075 	thr->valstack_top++;
23076 
23077 	return (void *) buf_data;
23078 }
23079 
duk_push_fixed_buffer_nozero(duk_hthread * thr,duk_size_t len)23080 DUK_INTERNAL void *duk_push_fixed_buffer_nozero(duk_hthread *thr, duk_size_t len) {
23081 	DUK_ASSERT_API_ENTRY(thr);
23082 	return duk_push_buffer_raw(thr, len, DUK_BUF_FLAG_NOZERO);
23083 }
23084 
duk_push_fixed_buffer_zero(duk_hthread * thr,duk_size_t len)23085 DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_hthread *thr, duk_size_t len) {
23086 	void *ptr;
23087 
23088 	DUK_ASSERT_API_ENTRY(thr);
23089 
23090 	ptr = duk_push_buffer_raw(thr, len, 0);
23091 	DUK_ASSERT(ptr != NULL);
23092 #if !defined(DUK_USE_ZERO_BUFFER_DATA)
23093 	/* ES2015 requires zeroing even when DUK_USE_ZERO_BUFFER_DATA
23094 	 * is not set.
23095 	 */
23096 	duk_memzero((void *) ptr, (size_t) len);
23097 #endif
23098 	return ptr;
23099 }
23100 
23101 #if defined(DUK_USE_ES6_PROXY)
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23102 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23103 	duk_hobject *h_target;
23104 	duk_hobject *h_handler;
23105 	duk_hproxy *h_proxy;
23106 	duk_tval *tv_slot;
23107 	duk_uint_t flags;
23108 
23109 	DUK_ASSERT_API_ENTRY(thr);
23110 	DUK_UNREF(proxy_flags);
23111 
23112 	/* DUK__CHECK_SPACE() unnecessary because the Proxy is written to
23113 	 * value stack in-place.
23114 	 */
23115 #if 0
23116 	DUK__CHECK_SPACE();
23117 #endif
23118 
23119 	/* Reject a proxy object as the target because it would need
23120 	 * special handling in property lookups.  (ES2015 has no such
23121 	 * restriction.)
23122 	 */
23123 	h_target = duk_require_hobject_promote_mask(thr, -2, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23124 	DUK_ASSERT(h_target != NULL);
23125 	if (DUK_HOBJECT_IS_PROXY(h_target)) {
23126 		goto fail_args;
23127 	}
23128 
23129 	/* Reject a proxy object as the handler because it would cause
23130 	 * potentially unbounded recursion.  (ES2015 has no such
23131 	 * restriction.)
23132 	 *
23133 	 * There's little practical reason to use a lightfunc or a plain
23134 	 * buffer as the handler table: one could only provide traps via
23135 	 * their prototype objects (Function.prototype and ArrayBuffer.prototype).
23136 	 * Even so, as lightfuncs and plain buffers mimic their object
23137 	 * counterparts, they're promoted and accepted here.
23138 	 */
23139 	h_handler = duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
23140 	DUK_ASSERT(h_handler != NULL);
23141 	if (DUK_HOBJECT_IS_PROXY(h_handler)) {
23142 		goto fail_args;
23143 	}
23144 
23145 	/* XXX: Proxy object currently has no prototype, so ToPrimitive()
23146 	 * coercion fails which is a bit confusing.
23147 	 */
23148 
23149 	/* CALLABLE and CONSTRUCTABLE flags are copied from the (initial)
23150 	 * target, see ES2015 Sections 9.5.15 and 9.5.13.
23151 	 */
23152 	flags = DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h_target) &
23153 	        (DUK_HOBJECT_FLAG_CALLABLE | DUK_HOBJECT_FLAG_CONSTRUCTABLE);
23154 	flags |= DUK_HOBJECT_FLAG_EXTENSIBLE |
23155 	         DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ;
23156 	if (flags & DUK_HOBJECT_FLAG_CALLABLE) {
23157 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_FUNCTION) |
23158 		         DUK_HOBJECT_FLAG_SPECIAL_CALL;
23159 	} else {
23160 		flags |= DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT);
23161 	}
23162 
23163 	h_proxy = duk_hproxy_alloc(thr, flags);
23164 	DUK_ASSERT(h_proxy != NULL);
23165 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_proxy) == NULL);
23166 
23167 	/* Initialize Proxy target and handler references; avoid INCREF
23168 	 * by stealing the value stack refcounts via direct value stack
23169 	 * manipulation.  INCREF is needed for the Proxy itself however.
23170 	 */
23171 	DUK_ASSERT(h_target != NULL);
23172 	h_proxy->target = h_target;
23173 	DUK_ASSERT(h_handler != NULL);
23174 	h_proxy->handler = h_handler;
23175 	DUK_ASSERT_HPROXY_VALID(h_proxy);
23176 
23177 	DUK_ASSERT(duk_get_hobject(thr, -2) == h_target);
23178 	DUK_ASSERT(duk_get_hobject(thr, -1) == h_handler);
23179 	tv_slot = thr->valstack_top - 2;
23180 	DUK_ASSERT(tv_slot >= thr->valstack_bottom);
23181 	DUK_TVAL_SET_OBJECT(tv_slot, (duk_hobject *) h_proxy);
23182 	DUK_HOBJECT_INCREF(thr, (duk_hobject *) h_proxy);
23183 	tv_slot++;
23184 	DUK_TVAL_SET_UNDEFINED(tv_slot);  /* [ ... target handler ] -> [ ... proxy undefined ] */
23185 	thr->valstack_top = tv_slot;      /* -> [ ... proxy ] */
23186 
23187 	DUK_DD(DUK_DDPRINT("created Proxy: %!iT", duk_get_tval(thr, -1)));
23188 
23189 	return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom - 1);
23190 
23191  fail_args:
23192 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23193 	DUK_WO_NORETURN(return 0;);
23194 }
23195 #else  /* DUK_USE_ES6_PROXY */
duk_push_proxy(duk_hthread * thr,duk_uint_t proxy_flags)23196 DUK_EXTERNAL duk_idx_t duk_push_proxy(duk_hthread *thr, duk_uint_t proxy_flags) {
23197 	DUK_ASSERT_API_ENTRY(thr);
23198 	DUK_UNREF(proxy_flags);
23199 	DUK_ERROR_UNSUPPORTED(thr);
23200 	DUK_WO_NORETURN(return 0;);
23201 }
23202 #endif  /* DUK_USE_ES6_PROXY */
23203 
23204 #if defined(DUK_USE_ASSERTIONS)
duk__validate_push_heapptr(duk_hthread * thr,void * ptr)23205 DUK_LOCAL void duk__validate_push_heapptr(duk_hthread *thr, void *ptr) {
23206 	duk_heaphdr *h;
23207 	duk_heaphdr *curr;
23208 	duk_bool_t found = 0;
23209 
23210 	h = (duk_heaphdr *) ptr;
23211 	if (h == NULL) {
23212 		/* Allowed. */
23213 		return;
23214 	}
23215 	DUK_ASSERT(h != NULL);
23216 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
23217 
23218 	/* One particular problem case is where an object has been
23219 	 * queued for finalization but the finalizer hasn't yet been
23220 	 * executed.
23221 	 *
23222 	 * Corner case: we're running in a finalizer for object X, and
23223 	 * user code calls duk_push_heapptr() for X itself.  In this
23224 	 * case X will be in finalize_list, and we can detect the case
23225 	 * by seeing that X's FINALIZED flag is set (which is done before
23226 	 * the finalizer starts executing).
23227 	 */
23228 #if defined(DUK_USE_FINALIZER_SUPPORT)
23229 	for (curr = thr->heap->finalize_list;
23230 	     curr != NULL;
23231 	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23232 		/* FINALIZABLE is set for all objects on finalize_list
23233 		 * except for an object being finalized right now.  So
23234 		 * can't assert here.
23235 		 */
23236 #if 0
23237 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));
23238 #endif
23239 
23240 		if (curr == h) {
23241 			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
23242 				/* Object is currently being finalized. */
23243 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23244 				found = 1;
23245 			} else {
23246 				/* Not being finalized but on finalize_list,
23247 				 * allowed since Duktape 2.1.
23248 				 */
23249 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23250 				found = 1;
23251 			}
23252 		}
23253 	}
23254 #endif  /* DUK_USE_FINALIZER_SUPPORT */
23255 
23256 #if defined(DUK_USE_REFERENCE_COUNTING)
23257 	/* Because refzero_list is now processed to completion inline with
23258 	 * no side effects, it's always empty here.
23259 	 */
23260 	DUK_ASSERT(thr->heap->refzero_list == NULL);
23261 #endif
23262 
23263 	/* If not present in finalize_list (or refzero_list), it
23264 	 * must be either in heap_allocated or the string table.
23265 	 */
23266 	if (DUK_HEAPHDR_IS_STRING(h)) {
23267 		duk_uint32_t i;
23268 		duk_hstring *str;
23269 		duk_heap *heap = thr->heap;
23270 
23271 		DUK_ASSERT(found == 0);
23272 		for (i = 0; i < heap->st_size; i++) {
23273 #if defined(DUK_USE_STRTAB_PTRCOMP)
23274 			str = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
23275 #else
23276 			str = heap->strtable[i];
23277 #endif
23278 			while (str != NULL) {
23279 				if (str == (duk_hstring *) h) {
23280 					DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23281 					found = 1;
23282 					break;
23283 				}
23284 				str = str->hdr.h_next;
23285 			}
23286 		}
23287 		DUK_ASSERT(found != 0);
23288 	} else {
23289 		for (curr = thr->heap->heap_allocated;
23290 		     curr != NULL;
23291 		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
23292 			if (curr == h) {
23293 				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
23294 				found = 1;
23295 			}
23296 		}
23297 		DUK_ASSERT(found != 0);
23298 	}
23299 }
23300 #endif  /* DUK_USE_ASSERTIONS */
23301 
duk_push_heapptr(duk_hthread * thr,void * ptr)23302 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_hthread *thr, void *ptr) {
23303 	duk_idx_t ret;
23304 	duk_tval *tv;
23305 
23306 	DUK_ASSERT_API_ENTRY(thr);
23307 
23308 	/* Reviving an object using a heap pointer is a dangerous API
23309 	 * operation: if the application doesn't guarantee that the
23310 	 * pointer target is always reachable, difficult-to-diagnose
23311 	 * problems may ensue.  Try to validate the 'ptr' argument to
23312 	 * the extent possible.
23313 	 */
23314 
23315 #if defined(DUK_USE_ASSERTIONS)
23316 	duk__validate_push_heapptr(thr, ptr);
23317 #endif
23318 
23319 	DUK__CHECK_SPACE();
23320 
23321 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23322 	tv = thr->valstack_top++;
23323 
23324 	if (ptr == NULL) {
23325 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
23326 		return ret;
23327 	}
23328 
23329 	DUK_ASSERT_HEAPHDR_VALID((duk_heaphdr *) ptr);
23330 
23331 	/* If the argument is on finalize_list it has technically been
23332 	 * unreachable before duk_push_heapptr() but it's still safe to
23333 	 * push it.  Starting from Duktape 2.1 allow application code to
23334 	 * do so.  There are two main cases:
23335 	 *
23336 	 *   (1) The object is on the finalize_list and we're called by
23337 	 *       the finalizer for the object being finalized.  In this
23338 	 *       case do nothing: finalize_list handling will deal with
23339 	 *       the object queueing.  This is detected by the object not
23340 	 *       having a FINALIZABLE flag despite being on the finalize_list;
23341 	 *       the flag is cleared for the object being finalized only.
23342 	 *
23343 	 *   (2) The object is on the finalize_list but is not currently
23344 	 *       being processed.  In this case the object can be queued
23345 	 *       back to heap_allocated with a few flags cleared, in effect
23346 	 *       cancelling the finalizer.
23347 	 */
23348 	if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) ptr))) {
23349 		duk_heaphdr *curr;
23350 
23351 		DUK_D(DUK_DPRINT("duk_push_heapptr() with a pointer on finalize_list, autorescue"));
23352 
23353 		curr = (duk_heaphdr *) ptr;
23354 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
23355 
23356 		/* Because FINALIZED is set prior to finalizer call, it will
23357 		 * be set for the object being currently finalized, but not
23358 		 * for other objects on finalize_list.
23359 		 */
23360 		DUK_HEAPHDR_CLEAR_FINALIZED(curr);
23361 
23362 		/* Dequeue object from finalize_list and queue it back to
23363 		 * heap_allocated.
23364 		 */
23365 #if defined(DUK_USE_REFERENCE_COUNTING)
23366 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);  /* Preincremented on finalize_list insert. */
23367 		DUK_HEAPHDR_PREDEC_REFCOUNT(curr);
23368 #endif
23369 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(thr->heap, curr);
23370 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(thr->heap, curr);
23371 
23372 		/* Continue with the rest. */
23373 	}
23374 
23375 	switch (DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr)) {
23376 	case DUK_HTYPE_STRING:
23377 		DUK_TVAL_SET_STRING(tv, (duk_hstring *) ptr);
23378 		break;
23379 	case DUK_HTYPE_OBJECT:
23380 		DUK_TVAL_SET_OBJECT(tv, (duk_hobject *) ptr);
23381 		break;
23382 	default:
23383 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) ptr) == DUK_HTYPE_BUFFER);
23384 		DUK_TVAL_SET_BUFFER(tv, (duk_hbuffer *) ptr);
23385 		break;
23386 	}
23387 
23388 	DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) ptr);
23389 
23390 	return ret;
23391 }
23392 
23393 /* Push object with no prototype, i.e. a "bare" object. */
duk_push_bare_object(duk_hthread * thr)23394 DUK_EXTERNAL duk_idx_t duk_push_bare_object(duk_hthread *thr) {
23395 	DUK_ASSERT_API_ENTRY(thr);
23396 
23397 	(void) duk_push_object_helper(thr,
23398 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
23399 	                              DUK_HOBJECT_FLAG_FASTREFS |
23400 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
23401 	                              -1);  /* no prototype */
23402 	return duk_get_top_index_unsafe(thr);
23403 }
23404 
duk_push_hstring(duk_hthread * thr,duk_hstring * h)23405 DUK_INTERNAL void duk_push_hstring(duk_hthread *thr, duk_hstring *h) {
23406 	duk_tval tv;
23407 
23408 	DUK_ASSERT_API_ENTRY(thr);
23409 	DUK_ASSERT(h != NULL);
23410 
23411 	DUK_TVAL_SET_STRING(&tv, h);
23412 	duk_push_tval(thr, &tv);
23413 }
23414 
duk_push_hstring_stridx(duk_hthread * thr,duk_small_uint_t stridx)23415 DUK_INTERNAL void duk_push_hstring_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
23416 	DUK_ASSERT_API_ENTRY(thr);
23417 	DUK_ASSERT_STRIDX_VALID(stridx);
23418 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
23419 }
23420 
duk_push_hstring_empty(duk_hthread * thr)23421 DUK_INTERNAL void duk_push_hstring_empty(duk_hthread *thr) {
23422 	DUK_ASSERT_API_ENTRY(thr);
23423 	duk_push_hstring(thr, DUK_HTHREAD_GET_STRING(thr, DUK_STRIDX_EMPTY_STRING));
23424 }
23425 
duk_push_hobject(duk_hthread * thr,duk_hobject * h)23426 DUK_INTERNAL void duk_push_hobject(duk_hthread *thr, duk_hobject *h) {
23427 	duk_tval tv;
23428 
23429 	DUK_ASSERT_API_ENTRY(thr);
23430 	DUK_ASSERT(h != NULL);
23431 
23432 	DUK_TVAL_SET_OBJECT(&tv, h);
23433 	duk_push_tval(thr, &tv);
23434 }
23435 
duk_push_hbuffer(duk_hthread * thr,duk_hbuffer * h)23436 DUK_INTERNAL void duk_push_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
23437 	duk_tval tv;
23438 
23439 	DUK_ASSERT_API_ENTRY(thr);
23440 	DUK_ASSERT(h != NULL);
23441 
23442 	DUK_TVAL_SET_BUFFER(&tv, h);
23443 	duk_push_tval(thr, &tv);
23444 }
23445 
duk_push_hobject_bidx(duk_hthread * thr,duk_small_int_t builtin_idx)23446 DUK_INTERNAL void duk_push_hobject_bidx(duk_hthread *thr, duk_small_int_t builtin_idx) {
23447 	DUK_ASSERT_API_ENTRY(thr);
23448 	DUK_ASSERT(builtin_idx >= 0 && builtin_idx < DUK_NUM_BUILTINS);
23449 	DUK_ASSERT(thr->builtins[builtin_idx] != NULL);
23450 
23451 	duk_push_hobject(thr, thr->builtins[builtin_idx]);
23452 }
23453 
23454 /*
23455  *  Poppers
23456  */
23457 
duk__pop_n_unsafe_raw(duk_hthread * thr,duk_idx_t count)23458 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_n_unsafe_raw(duk_hthread *thr, duk_idx_t count) {
23459 	duk_tval *tv;
23460 #if defined(DUK_USE_REFERENCE_COUNTING)
23461 	duk_tval *tv_end;
23462 #endif
23463 
23464 	DUK_ASSERT_CTX_VALID(thr);
23465 	DUK_ASSERT(count >= 0);
23466 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23467 
23468 #if defined(DUK_USE_REFERENCE_COUNTING)
23469 	tv = thr->valstack_top;
23470 	tv_end = tv - count;
23471 	while (tv != tv_end) {
23472 		tv--;
23473 		DUK_ASSERT(tv >= thr->valstack_bottom);
23474 		DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
23475 	}
23476 	thr->valstack_top = tv;
23477 	DUK_REFZERO_CHECK_FAST(thr);
23478 #else
23479 	tv = thr->valstack_top;
23480 	while (count > 0) {
23481 		count--;
23482 		tv--;
23483 		DUK_ASSERT(tv >= thr->valstack_bottom);
23484 		DUK_TVAL_SET_UNDEFINED(tv);
23485 	}
23486 	thr->valstack_top = tv;
23487 #endif
23488 
23489 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23490 }
23491 
duk_pop_n(duk_hthread * thr,duk_idx_t count)23492 DUK_EXTERNAL void duk_pop_n(duk_hthread *thr, duk_idx_t count) {
23493 	DUK_ASSERT_API_ENTRY(thr);
23494 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23495 
23496 	if (DUK_UNLIKELY((duk_uidx_t) (thr->valstack_top - thr->valstack_bottom) < (duk_uidx_t) count)) {
23497 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23498 		DUK_WO_NORETURN(return;);
23499 	}
23500 	DUK_ASSERT(count >= 0);
23501 
23502 	duk__pop_n_unsafe_raw(thr, count);
23503 }
23504 
23505 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23506 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23507 	DUK_ASSERT_API_ENTRY(thr);
23508 	duk_pop_n(thr, count);
23509 }
23510 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_n_unsafe(duk_hthread * thr,duk_idx_t count)23511 DUK_INTERNAL void duk_pop_n_unsafe(duk_hthread *thr, duk_idx_t count) {
23512 	DUK_ASSERT_API_ENTRY(thr);
23513 	duk__pop_n_unsafe_raw(thr, count);
23514 }
23515 #endif  /* DUK_USE_PREFER_SIZE */
23516 
23517 /* Pop N elements without DECREF (in effect "stealing" any actual refcounts). */
23518 #if defined(DUK_USE_REFERENCE_COUNTING)
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23519 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23520 	duk_tval *tv;
23521 
23522 	DUK_ASSERT_API_ENTRY(thr);
23523 	DUK_ASSERT(count >= 0);
23524 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23525 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) count);
23526 
23527 	tv = thr->valstack_top;
23528 	while (count > 0) {
23529 		count--;
23530 		tv--;
23531 		DUK_ASSERT(tv >= thr->valstack_bottom);
23532 		DUK_TVAL_SET_UNDEFINED(tv);
23533 	}
23534 	thr->valstack_top = tv;
23535 
23536 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23537 }
23538 #else  /* DUK_USE_REFERENCE_COUNTING */
duk_pop_n_nodecref_unsafe(duk_hthread * thr,duk_idx_t count)23539 DUK_INTERNAL void duk_pop_n_nodecref_unsafe(duk_hthread *thr, duk_idx_t count) {
23540 	DUK_ASSERT_API_ENTRY(thr);
23541 	duk_pop_n_unsafe(thr, count);
23542 }
23543 #endif  /* DUK_USE_REFERENCE_COUNTING */
23544 
23545 /* Popping one element is called so often that when footprint is not an issue,
23546  * compile a specialized function for it.
23547  */
23548 #if defined(DUK_USE_PREFER_SIZE)
duk_pop(duk_hthread * thr)23549 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23550 	DUK_ASSERT_API_ENTRY(thr);
23551 	duk_pop_n(thr, 1);
23552 }
duk_pop_unsafe(duk_hthread * thr)23553 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23554 	DUK_ASSERT_API_ENTRY(thr);
23555 	duk_pop_n_unsafe(thr, 1);
23556 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23557 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23558 	DUK_ASSERT_API_ENTRY(thr);
23559 	duk_pop_n_nodecref_unsafe(thr, 1);
23560 }
23561 #else  /* DUK_USE_PREFER_SIZE */
duk__pop_unsafe_raw(duk_hthread * thr)23562 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_unsafe_raw(duk_hthread *thr) {
23563 	duk_tval *tv;
23564 
23565 	DUK_ASSERT_CTX_VALID(thr);
23566 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23567 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23568 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23569 
23570 	tv = --thr->valstack_top;
23571 	DUK_ASSERT(tv >= thr->valstack_bottom);
23572 #if defined(DUK_USE_REFERENCE_COUNTING)
23573 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23574 #else
23575 	DUK_TVAL_SET_UNDEFINED(tv);
23576 #endif
23577 
23578 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23579 }
duk_pop(duk_hthread * thr)23580 DUK_EXTERNAL void duk_pop(duk_hthread *thr) {
23581 	DUK_ASSERT_API_ENTRY(thr);
23582 
23583 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23584 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23585 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23586 		DUK_WO_NORETURN(return;);
23587 	}
23588 
23589 	duk__pop_unsafe_raw(thr);
23590 }
duk_pop_unsafe(duk_hthread * thr)23591 DUK_INTERNAL void duk_pop_unsafe(duk_hthread *thr) {
23592 	DUK_ASSERT_API_ENTRY(thr);
23593 	duk__pop_unsafe_raw(thr);
23594 }
duk_pop_nodecref_unsafe(duk_hthread * thr)23595 DUK_INTERNAL void duk_pop_nodecref_unsafe(duk_hthread *thr) {
23596 	duk_tval *tv;
23597 
23598 	DUK_ASSERT_API_ENTRY(thr);
23599 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23600 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23601 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23602 
23603 	tv = --thr->valstack_top;
23604 	DUK_ASSERT(tv >= thr->valstack_bottom);
23605 	DUK_TVAL_SET_UNDEFINED(tv);
23606 
23607 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23608 }
23609 #endif  /* !DUK_USE_PREFER_SIZE */
23610 
23611 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_undefined(duk_hthread * thr)23612 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23613 	DUK_ASSERT_API_ENTRY(thr);
23614 	duk_pop_nodecref_unsafe(thr);
23615 }
23616 #else  /* DUK_USE_PREFER_SIZE */
duk_pop_undefined(duk_hthread * thr)23617 DUK_INTERNAL void duk_pop_undefined(duk_hthread *thr) {
23618 	DUK_ASSERT_API_ENTRY(thr);
23619 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23620 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23621 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 1);
23622 
23623 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23624 	thr->valstack_top--;
23625 
23626 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23627 }
23628 #endif  /* !DUK_USE_PREFER_SIZE */
23629 
23630 #if defined(DUK_USE_PREFER_SIZE)
duk_pop_2(duk_hthread * thr)23631 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23632 	DUK_ASSERT_API_ENTRY(thr);
23633 	duk_pop_n(thr, 2);
23634 }
duk_pop_2_unsafe(duk_hthread * thr)23635 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23636 	DUK_ASSERT_API_ENTRY(thr);
23637 	duk_pop_n_unsafe(thr, 2);
23638 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23639 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23640 	DUK_ASSERT_API_ENTRY(thr);
23641 	duk_pop_n_nodecref_unsafe(thr, 2);
23642 }
23643 #else
duk__pop_2_unsafe_raw(duk_hthread * thr)23644 DUK_LOCAL DUK_ALWAYS_INLINE void duk__pop_2_unsafe_raw(duk_hthread *thr) {
23645 	duk_tval *tv;
23646 
23647 	DUK_ASSERT_CTX_VALID(thr);
23648 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23649 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23650 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23651 
23652 	tv = --thr->valstack_top;
23653 	DUK_ASSERT(tv >= thr->valstack_bottom);
23654 #if defined(DUK_USE_REFERENCE_COUNTING)
23655 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23656 #else
23657 	DUK_TVAL_SET_UNDEFINED(tv);
23658 #endif
23659 	tv = --thr->valstack_top;
23660 	DUK_ASSERT(tv >= thr->valstack_bottom);
23661 #if defined(DUK_USE_REFERENCE_COUNTING)
23662 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);  /* side effects */
23663 #else
23664 	DUK_TVAL_SET_UNDEFINED(tv);
23665 #endif
23666 
23667 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23668 }
duk_pop_2(duk_hthread * thr)23669 DUK_EXTERNAL void duk_pop_2(duk_hthread *thr) {
23670 	DUK_ASSERT_API_ENTRY(thr);
23671 
23672 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23673 	if (DUK_UNLIKELY(thr->valstack_top - 2 < thr->valstack_bottom)) {
23674 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23675 		DUK_WO_NORETURN(return;);
23676 	}
23677 
23678 	duk__pop_2_unsafe_raw(thr);
23679 }
duk_pop_2_unsafe(duk_hthread * thr)23680 DUK_INTERNAL void duk_pop_2_unsafe(duk_hthread *thr) {
23681 	DUK_ASSERT_API_ENTRY(thr);
23682 	duk__pop_2_unsafe_raw(thr);
23683 }
duk_pop_2_nodecref_unsafe(duk_hthread * thr)23684 DUK_INTERNAL void duk_pop_2_nodecref_unsafe(duk_hthread *thr) {
23685 	DUK_ASSERT_API_ENTRY(thr);
23686 	DUK_ASSERT(thr->valstack_top != thr->valstack_bottom);
23687 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23688 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) >= (duk_size_t) 2);
23689 
23690 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 1));
23691 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top - 2));
23692 	thr->valstack_top -= 2;
23693 
23694 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23695 }
23696 #endif  /* !DUK_USE_PREFER_SIZE */
23697 
duk_pop_3(duk_hthread * thr)23698 DUK_EXTERNAL void duk_pop_3(duk_hthread *thr) {
23699 	DUK_ASSERT_API_ENTRY(thr);
23700 	duk_pop_n(thr, 3);
23701 }
23702 
duk_pop_3_unsafe(duk_hthread * thr)23703 DUK_INTERNAL void duk_pop_3_unsafe(duk_hthread *thr) {
23704 	DUK_ASSERT_API_ENTRY(thr);
23705 	duk_pop_n_unsafe(thr, 3);
23706 }
23707 
duk_pop_3_nodecref_unsafe(duk_hthread * thr)23708 DUK_INTERNAL void duk_pop_3_nodecref_unsafe(duk_hthread *thr) {
23709 	DUK_ASSERT_API_ENTRY(thr);
23710 	duk_pop_n_nodecref_unsafe(thr, 3);
23711 }
23712 
23713 /*
23714  *  Pack and unpack (pack value stack entries into an array and vice versa)
23715  */
23716 
23717 /* XXX: pack index range? array index offset? */
duk_pack(duk_hthread * thr,duk_idx_t count)23718 DUK_INTERNAL void duk_pack(duk_hthread *thr, duk_idx_t count) {
23719 	duk_tval *tv_src;
23720 	duk_tval *tv_dst;
23721 	duk_tval *tv_curr;
23722 	duk_tval *tv_limit;
23723 	duk_idx_t top;
23724 
23725 	DUK_ASSERT_API_ENTRY(thr);
23726 
23727 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23728 	top = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
23729 	DUK_ASSERT(top >= 0);
23730 	if (DUK_UNLIKELY((duk_uidx_t) count > (duk_uidx_t) top)) {
23731 		/* Also handles negative count. */
23732 		DUK_ERROR_RANGE_INVALID_COUNT(thr);
23733 		DUK_WO_NORETURN(return;);
23734 	}
23735 	DUK_ASSERT(count >= 0);
23736 
23737 	/* Wrapping is controlled by the check above: value stack top can be
23738 	 * at most DUK_USE_VALSTACK_LIMIT which is low enough so that
23739 	 * multiplying with sizeof(duk_tval) won't wrap.
23740 	 */
23741 	DUK_ASSERT(count >= 0 && count <= (duk_idx_t) DUK_USE_VALSTACK_LIMIT);
23742 	DUK_ASSERT((duk_size_t) count <= DUK_SIZE_MAX / sizeof(duk_tval));  /* no wrapping */
23743 
23744 	tv_dst = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);  /* XXX: uninitialized would be OK */
23745 	DUK_ASSERT(count == 0 || tv_dst != NULL);
23746 
23747 	/* Copy value stack values directly to the array part without
23748 	 * any refcount updates: net refcount changes are zero.
23749 	 */
23750 	tv_src = thr->valstack_top - count - 1;
23751 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, (size_t) count * sizeof(duk_tval));
23752 
23753 	/* Overwrite result array to final value stack location and wipe
23754 	 * the rest; no refcount operations needed.
23755 	 */
23756 
23757 	tv_dst = tv_src;  /* when count == 0, same as tv_src (OK) */
23758 	tv_src = thr->valstack_top - 1;
23759 	DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23760 
23761 	/* XXX: internal helper to wipe a value stack segment? */
23762 	tv_curr = tv_dst + 1;
23763 	tv_limit = thr->valstack_top;
23764 	while (tv_curr != tv_limit) {
23765 		/* Wipe policy: keep as 'undefined'. */
23766 		DUK_TVAL_SET_UNDEFINED(tv_curr);
23767 		tv_curr++;
23768 	}
23769 	thr->valstack_top = tv_dst + 1;
23770 }
23771 
duk_unpack_array_like(duk_hthread * thr,duk_idx_t idx)23772 DUK_INTERNAL duk_idx_t duk_unpack_array_like(duk_hthread *thr, duk_idx_t idx) {
23773 	duk_tval *tv;
23774 
23775 	DUK_ASSERT_API_ENTRY(thr);
23776 
23777 	tv = duk_require_tval(thr, idx);
23778 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv))) {
23779 		duk_hobject *h;
23780 		duk_uint32_t len;
23781 		duk_uint32_t i;
23782 
23783 		h = DUK_TVAL_GET_OBJECT(tv);
23784 		DUK_ASSERT(h != NULL);
23785 		DUK_UNREF(h);
23786 
23787 #if defined(DUK_USE_ARRAY_FASTPATH)  /* close enough */
23788 		if (DUK_LIKELY(DUK_HOBJECT_IS_ARRAY(h) &&
23789 		               ((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h))) {
23790 			duk_harray *h_arr;
23791 			duk_tval *tv_src;
23792 			duk_tval *tv_dst;
23793 
23794 			h_arr = (duk_harray *) h;
23795 			len = h_arr->length;
23796 			if (DUK_UNLIKELY(len >= 0x80000000UL)) {
23797 				goto fail_over_2g;
23798 			}
23799 			duk_require_stack(thr, (duk_idx_t) len);
23800 
23801 			/* The potential allocation in duk_require_stack() may
23802 			 * run a finalizer which modifies the argArray so that
23803 			 * e.g. becomes sparse.  So, we need to recheck that the
23804 			 * array didn't change size and that there's still a
23805 			 * valid backing array part.
23806 			 *
23807 			 * XXX: alternatively, could prevent finalizers for the
23808 			 * duration.
23809 			 */
23810 			if (DUK_UNLIKELY(len != h_arr->length ||
23811 			                 h_arr->length > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr))) {
23812 				goto skip_fast;
23813 			}
23814 
23815 			/* Main fast path: arguments array is almost always
23816 			 * an actual array (though it might also be an arguments
23817 			 * object).
23818 			 */
23819 
23820 			DUK_DDD(DUK_DDDPRINT("fast path for %ld elements", (long) h_arr->length));
23821 			tv_src = DUK_HOBJECT_A_GET_BASE(thr->heap, h);
23822 			tv_dst = thr->valstack_top;
23823 			while (len-- > 0) {
23824 				DUK_ASSERT(tv_dst < thr->valstack_end);
23825 				if (DUK_UNLIKELY(DUK_TVAL_IS_UNUSED(tv_src))) {
23826 					/* Gaps are very unlikely.  Skip over them,
23827 					 * without an ancestor lookup (technically
23828 					 * not compliant).
23829 					 */
23830 					DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_dst));  /* valstack policy */
23831 				} else {
23832 					DUK_TVAL_SET_TVAL(tv_dst, tv_src);
23833 					DUK_TVAL_INCREF(thr, tv_dst);
23834 				}
23835 				tv_src++;
23836 				tv_dst++;
23837 			}
23838 			DUK_ASSERT(tv_dst <= thr->valstack_end);
23839 			thr->valstack_top = tv_dst;
23840 			return (duk_idx_t) h_arr->length;
23841 		}
23842 	 skip_fast:
23843 #endif  /* DUK_USE_ARRAY_FASTPATH */
23844 
23845 		/* Slow path: actual lookups.  The initial 'length' lookup
23846 		 * decides the output length, regardless of side effects that
23847 		 * may resize or change the argArray while we read the
23848 		 * indices.
23849 		 */
23850 		idx = duk_normalize_index(thr, idx);
23851 		duk_get_prop_stridx(thr, idx, DUK_STRIDX_LENGTH);
23852 		len = duk_to_uint32(thr, -1);  /* ToUint32() coercion required */
23853 		if (DUK_UNLIKELY(len >= 0x80000000UL)) {
23854 			goto fail_over_2g;
23855 		}
23856 		duk_pop_unsafe(thr);
23857 		DUK_DDD(DUK_DDDPRINT("slow path for %ld elements", (long) len));
23858 
23859 		duk_require_stack(thr, (duk_idx_t) len);
23860 		for (i = 0; i < len; i++) {
23861 			duk_get_prop_index(thr, idx, (duk_uarridx_t) i);
23862 		}
23863 		return (duk_idx_t) len;
23864 	} else if (DUK_TVAL_IS_UNDEFINED(tv) || DUK_TVAL_IS_NULL(tv)) {
23865 		return 0;
23866 	}
23867 
23868 	DUK_ERROR_TYPE_INVALID_ARGS(thr);
23869 	DUK_WO_NORETURN(return 0;);
23870 
23871  fail_over_2g:
23872 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
23873 	DUK_WO_NORETURN(return 0;);
23874 }
23875 
23876 /*
23877  *  Error throwing
23878  */
23879 
duk_throw_raw(duk_hthread * thr)23880 DUK_EXTERNAL void duk_throw_raw(duk_hthread *thr) {
23881 	duk_tval *tv_val;
23882 
23883 	DUK_ASSERT_API_ENTRY(thr);
23884 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
23885 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
23886 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
23887 
23888 	if (DUK_UNLIKELY(thr->valstack_top == thr->valstack_bottom)) {
23889 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
23890 		DUK_WO_NORETURN(return;);
23891 	}
23892 
23893 	/* Errors are augmented when they are created, not when they are
23894 	 * thrown or re-thrown.  The current error handler, however, runs
23895 	 * just before an error is thrown.
23896 	 */
23897 
23898 	/* Sync so that augmentation sees up-to-date activations, NULL
23899 	 * thr->ptr_curr_pc so that it's not used if side effects occur
23900 	 * in augmentation or longjmp handling.
23901 	 */
23902 	duk_hthread_sync_and_null_currpc(thr);
23903 
23904 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
23905 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (before throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
23906 	duk_err_augment_error_throw(thr);
23907 #endif
23908 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (API): %!dT (after throw augment)", (duk_tval *) duk_get_tval(thr, -1)));
23909 
23910 	tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
23911 	duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, tv_val);
23912 #if defined(DUK_USE_DEBUGGER_SUPPORT)
23913 	duk_err_check_debugger_integration(thr);
23914 #endif
23915 
23916 	/* thr->heap->lj.jmpbuf_ptr is checked by duk_err_longjmp() so we don't
23917 	 * need to check that here.  If the value is NULL, a fatal error occurs
23918 	 * because we can't return.
23919 	 */
23920 
23921 	duk_err_longjmp(thr);
23922 	DUK_UNREACHABLE();
23923 }
23924 
duk_fatal_raw(duk_hthread * thr,const char * err_msg)23925 DUK_EXTERNAL void duk_fatal_raw(duk_hthread *thr, const char *err_msg) {
23926 	DUK_ASSERT_API_ENTRY(thr);
23927 	DUK_ASSERT(thr != NULL);
23928 	DUK_ASSERT(thr->heap != NULL);
23929 	DUK_ASSERT(thr->heap->fatal_func != NULL);
23930 
23931 	DUK_D(DUK_DPRINT("fatal error occurred: %s", err_msg ? err_msg : "NULL"));
23932 
23933 	/* fatal_func should be noreturn, but noreturn declarations on function
23934 	 * pointers has a very spotty support apparently so it's not currently
23935 	 * done.
23936 	 */
23937 	thr->heap->fatal_func(thr->heap->heap_udata, err_msg);
23938 
23939 	/* If the fatal handler returns, all bets are off.  It'd be nice to
23940 	 * print something here but since we don't want to depend on stdio,
23941 	 * there's no way to do so portably.
23942 	 */
23943 	DUK_D(DUK_DPRINT("fatal error handler returned, all bets are off!"));
23944 	for (;;) {
23945 		/* loop forever, don't return (function marked noreturn) */
23946 	}
23947 }
23948 
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)23949 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) {
23950 	DUK_ASSERT_API_ENTRY(thr);
23951 
23952 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23953 	(void) duk_throw(thr);
23954 	DUK_WO_NORETURN(return;);
23955 }
23956 
duk_error_raw(duk_hthread * thr,duk_errcode_t err_code,const char * filename,duk_int_t line,const char * fmt,...)23957 DUK_EXTERNAL void duk_error_raw(duk_hthread *thr, duk_errcode_t err_code, const char *filename, duk_int_t line, const char *fmt, ...) {
23958 	va_list ap;
23959 
23960 	DUK_ASSERT_API_ENTRY(thr);
23961 
23962 	va_start(ap, fmt);
23963 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23964 	va_end(ap);
23965 	(void) duk_throw(thr);
23966 	DUK_WO_NORETURN(return;);
23967 }
23968 
23969 #if !defined(DUK_USE_VARIADIC_MACROS)
23970 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));
23971 
duk__throw_error_from_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,va_list ap)23972 DUK_LOCAL void duk__throw_error_from_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, va_list ap) {
23973 	const char *filename;
23974 	duk_int_t line;
23975 
23976 	DUK_ASSERT_CTX_VALID(thr);
23977 
23978 	filename = duk_api_global_filename;
23979 	line = duk_api_global_line;
23980 	duk_api_global_filename = NULL;
23981 	duk_api_global_line = 0;
23982 
23983 	duk_push_error_object_va_raw(thr, err_code, filename, line, fmt, ap);
23984 	(void) duk_throw(thr);
23985 	DUK_WO_NORETURN(return;);
23986 }
23987 
23988 #define DUK__ERROR_STASH_SHARED(code) do { \
23989 		va_list ap; \
23990 		va_start(ap, fmt); \
23991 		duk__throw_error_from_stash(thr, (code), fmt, ap); \
23992 		va_end(ap); \
23993 		DUK_WO_NORETURN(return 0;); \
23994 	} while (0)
23995 
duk_error_stash(duk_hthread * thr,duk_errcode_t err_code,const char * fmt,...)23996 DUK_EXTERNAL duk_ret_t duk_error_stash(duk_hthread *thr, duk_errcode_t err_code, const char *fmt, ...) {
23997 	DUK_ASSERT_API_ENTRY(thr);
23998 	DUK__ERROR_STASH_SHARED(err_code);
23999 }
duk_generic_error_stash(duk_hthread * thr,const char * fmt,...)24000 DUK_EXTERNAL duk_ret_t duk_generic_error_stash(duk_hthread *thr, const char *fmt, ...) {
24001 	DUK_ASSERT_API_ENTRY(thr);
24002 	DUK__ERROR_STASH_SHARED(DUK_ERR_ERROR);
24003 }
duk_eval_error_stash(duk_hthread * thr,const char * fmt,...)24004 DUK_EXTERNAL duk_ret_t duk_eval_error_stash(duk_hthread *thr, const char *fmt, ...) {
24005 	DUK_ASSERT_API_ENTRY(thr);
24006 	DUK__ERROR_STASH_SHARED(DUK_ERR_EVAL_ERROR);
24007 }
duk_range_error_stash(duk_hthread * thr,const char * fmt,...)24008 DUK_EXTERNAL duk_ret_t duk_range_error_stash(duk_hthread *thr, const char *fmt, ...) {
24009 	DUK_ASSERT_API_ENTRY(thr);
24010 	DUK__ERROR_STASH_SHARED(DUK_ERR_RANGE_ERROR);
24011 }
duk_reference_error_stash(duk_hthread * thr,const char * fmt,...)24012 DUK_EXTERNAL duk_ret_t duk_reference_error_stash(duk_hthread *thr, const char *fmt, ...) {
24013 	DUK_ASSERT_API_ENTRY(thr);
24014 	DUK__ERROR_STASH_SHARED(DUK_ERR_REFERENCE_ERROR);
24015 }
duk_syntax_error_stash(duk_hthread * thr,const char * fmt,...)24016 DUK_EXTERNAL duk_ret_t duk_syntax_error_stash(duk_hthread *thr, const char *fmt, ...) {
24017 	DUK_ASSERT_API_ENTRY(thr);
24018 	DUK__ERROR_STASH_SHARED(DUK_ERR_SYNTAX_ERROR);
24019 }
duk_type_error_stash(duk_hthread * thr,const char * fmt,...)24020 DUK_EXTERNAL duk_ret_t duk_type_error_stash(duk_hthread *thr, const char *fmt, ...) {
24021 	DUK_ASSERT_API_ENTRY(thr);
24022 	DUK__ERROR_STASH_SHARED(DUK_ERR_TYPE_ERROR);
24023 }
duk_uri_error_stash(duk_hthread * thr,const char * fmt,...)24024 DUK_EXTERNAL duk_ret_t duk_uri_error_stash(duk_hthread *thr, const char *fmt, ...) {
24025 	DUK_ASSERT_API_ENTRY(thr);
24026 	DUK__ERROR_STASH_SHARED(DUK_ERR_URI_ERROR);
24027 }
24028 #endif  /* DUK_USE_VARIADIC_MACROS */
24029 
24030 /*
24031  *  Comparison
24032  */
24033 
duk_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24034 DUK_EXTERNAL duk_bool_t duk_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24035 	duk_tval *tv1, *tv2;
24036 
24037 	DUK_ASSERT_API_ENTRY(thr);
24038 
24039 	tv1 = duk_get_tval(thr, idx1);
24040 	tv2 = duk_get_tval(thr, idx2);
24041 	if ((tv1 == NULL) || (tv2 == NULL)) {
24042 		return 0;
24043 	}
24044 
24045 	/* Coercion may be needed, the helper handles that by pushing the
24046 	 * tagged values to the stack.
24047 	 */
24048 	return duk_js_equals(thr, tv1, tv2);
24049 }
24050 
duk_strict_equals(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24051 DUK_EXTERNAL duk_bool_t duk_strict_equals(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24052 	duk_tval *tv1, *tv2;
24053 
24054 	DUK_ASSERT_API_ENTRY(thr);
24055 
24056 	tv1 = duk_get_tval(thr, idx1);
24057 	tv2 = duk_get_tval(thr, idx2);
24058 	if ((tv1 == NULL) || (tv2 == NULL)) {
24059 		return 0;
24060 	}
24061 
24062 	/* No coercions or other side effects, so safe */
24063 	return duk_js_strict_equals(tv1, tv2);
24064 }
24065 
duk_samevalue(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24066 DUK_EXTERNAL duk_bool_t duk_samevalue(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24067 	duk_tval *tv1, *tv2;
24068 
24069 	DUK_ASSERT_API_ENTRY(thr);
24070 
24071 	tv1 = duk_get_tval(thr, idx1);
24072 	tv2 = duk_get_tval(thr, idx2);
24073 	if ((tv1 == NULL) || (tv2 == NULL)) {
24074 		return 0;
24075 	}
24076 
24077 	/* No coercions or other side effects, so safe */
24078 	return duk_js_samevalue(tv1, tv2);
24079 }
24080 
24081 /*
24082  *  instanceof
24083  */
24084 
duk_instanceof(duk_hthread * thr,duk_idx_t idx1,duk_idx_t idx2)24085 DUK_EXTERNAL duk_bool_t duk_instanceof(duk_hthread *thr, duk_idx_t idx1, duk_idx_t idx2) {
24086 	duk_tval *tv1, *tv2;
24087 
24088 	DUK_ASSERT_API_ENTRY(thr);
24089 
24090 	/* Index validation is strict, which differs from duk_equals().
24091 	 * The strict behavior mimics how instanceof itself works, e.g.
24092 	 * it is a TypeError if rval is not a -callable- object.  It would
24093 	 * be somewhat inconsistent if rval would be allowed to be
24094 	 * non-existent without a TypeError.
24095 	 */
24096 	tv1 = duk_require_tval(thr, idx1);
24097 	DUK_ASSERT(tv1 != NULL);
24098 	tv2 = duk_require_tval(thr, idx2);
24099 	DUK_ASSERT(tv2 != NULL);
24100 
24101 	return duk_js_instanceof(thr, tv1, tv2);
24102 }
24103 
24104 /*
24105  *  Lightfunc
24106  */
24107 
duk_push_lightfunc_name_raw(duk_hthread * thr,duk_c_function func,duk_small_uint_t lf_flags)24108 DUK_INTERNAL void duk_push_lightfunc_name_raw(duk_hthread *thr, duk_c_function func, duk_small_uint_t lf_flags) {
24109 	/* Lightfunc name, includes Duktape/C native function pointer, which
24110 	 * can often be used to locate the function from a symbol table.
24111 	 * The name also includes the 16-bit duk_tval flags field because it
24112 	 * includes the magic value.  Because a single native function often
24113 	 * provides different functionality depending on the magic value, it
24114 	 * seems reasonably to include it in the name.
24115 	 *
24116 	 * On the other hand, a complicated name increases string table
24117 	 * pressure in low memory environments (but only when function name
24118 	 * is accessed).
24119 	 */
24120 
24121 	DUK_ASSERT_API_ENTRY(thr);
24122 
24123 	duk_push_literal(thr, "light_");
24124 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24125 	duk_push_sprintf(thr, "_%04x", (unsigned int) lf_flags);
24126 	duk_concat(thr, 3);
24127 }
24128 
duk_push_lightfunc_name(duk_hthread * thr,duk_tval * tv)24129 DUK_INTERNAL void duk_push_lightfunc_name(duk_hthread *thr, duk_tval *tv) {
24130 	duk_c_function func;
24131 	duk_small_uint_t lf_flags;
24132 
24133 	DUK_ASSERT_API_ENTRY(thr);
24134 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24135 
24136 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
24137 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24138 }
24139 
duk_push_lightfunc_tostring(duk_hthread * thr,duk_tval * tv)24140 DUK_INTERNAL void duk_push_lightfunc_tostring(duk_hthread *thr, duk_tval *tv) {
24141 	duk_c_function func;
24142 	duk_small_uint_t lf_flags;
24143 
24144 	DUK_ASSERT_API_ENTRY(thr);
24145 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv));
24146 
24147 	DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);  /* read before 'tv' potentially invalidated */
24148 	duk_push_literal(thr, "function ");
24149 	duk_push_lightfunc_name_raw(thr, func, lf_flags);
24150 	duk_push_literal(thr, "() { [lightfunc code] }");
24151 	duk_concat(thr, 3);
24152 }
24153 
24154 /*
24155  *  Function pointers
24156  *
24157  *  Printing function pointers is non-portable, so we do that by hex printing
24158  *  bytes from memory.
24159  */
24160 
duk_push_string_funcptr(duk_hthread * thr,duk_uint8_t * ptr,duk_size_t sz)24161 DUK_INTERNAL void duk_push_string_funcptr(duk_hthread *thr, duk_uint8_t *ptr, duk_size_t sz) {
24162 	duk_uint8_t buf[32 * 2];
24163 	duk_uint8_t *p, *q;
24164 	duk_small_uint_t i;
24165 	duk_small_uint_t t;
24166 
24167 	DUK_ASSERT_API_ENTRY(thr);
24168 	DUK_ASSERT(sz <= 32);  /* sanity limit for function pointer size */
24169 
24170 	p = buf;
24171 #if defined(DUK_USE_INTEGER_LE)
24172 	q = ptr + sz;
24173 #else
24174 	q = ptr;
24175 #endif
24176 	for (i = 0; i < sz; i++) {
24177 #if defined(DUK_USE_INTEGER_LE)
24178 		t = *(--q);
24179 #else
24180 		t = *(q++);
24181 #endif
24182 		*p++ = duk_lc_digits[t >> 4];
24183 		*p++ = duk_lc_digits[t & 0x0f];
24184 	}
24185 
24186 	duk_push_lstring(thr, (const char *) buf, sz * 2);
24187 }
24188 
24189 /*
24190  *  Push readable string summarizing duk_tval.  The operation is side effect
24191  *  free and will only throw from internal errors (e.g. out of memory).
24192  *  This is used by e.g. property access code to summarize a key/base safely,
24193  *  and is not intended to be fast (but small and safe).
24194  */
24195 
24196 /* String limits for summary strings. */
24197 #define DUK__READABLE_SUMMARY_MAXCHARS 96  /* maximum supported by helper */
24198 #define DUK__READABLE_STRING_MAXCHARS  32  /* for strings/symbols */
24199 #define DUK__READABLE_ERRMSG_MAXCHARS  96  /* for error messages */
24200 
24201 /* String sanitizer which escapes ASCII control characters and a few other
24202  * ASCII characters, passes Unicode as is, and replaces invalid UTF-8 with
24203  * question marks.  No errors are thrown for any input string, except in out
24204  * of memory situations.
24205  */
duk__push_hstring_readable_unicode(duk_hthread * thr,duk_hstring * h_input,duk_small_uint_t maxchars)24206 DUK_LOCAL void duk__push_hstring_readable_unicode(duk_hthread *thr, duk_hstring *h_input, duk_small_uint_t maxchars) {
24207 	const duk_uint8_t *p, *p_start, *p_end;
24208 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH * DUK__READABLE_SUMMARY_MAXCHARS +
24209 	                2 /*quotes*/ + 3 /*periods*/];
24210 	duk_uint8_t *q;
24211 	duk_ucodepoint_t cp;
24212 	duk_small_uint_t nchars;
24213 
24214 	DUK_ASSERT_CTX_VALID(thr);
24215 	DUK_ASSERT(h_input != NULL);
24216 	DUK_ASSERT(maxchars <= DUK__READABLE_SUMMARY_MAXCHARS);
24217 
24218 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24219 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24220 	p = p_start;
24221 	q = buf;
24222 
24223 	nchars = 0;
24224 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24225 	for (;;) {
24226 		if (p >= p_end) {
24227 			break;
24228 		}
24229 		if (nchars == maxchars) {
24230 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24231 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24232 			*q++ = (duk_uint8_t) DUK_ASC_PERIOD;
24233 			break;
24234 		}
24235 		if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
24236 			if (cp < 0x20 || cp == 0x7f || cp == DUK_ASC_SINGLEQUOTE || cp == DUK_ASC_BACKSLASH) {
24237 				DUK_ASSERT(DUK_UNICODE_MAX_XUTF8_LENGTH >= 4);  /* estimate is valid */
24238 				DUK_ASSERT((cp >> 4) <= 0x0f);
24239 				*q++ = (duk_uint8_t) DUK_ASC_BACKSLASH;
24240 				*q++ = (duk_uint8_t) DUK_ASC_LC_X;
24241 				*q++ = (duk_uint8_t) duk_lc_digits[cp >> 4];
24242 				*q++ = (duk_uint8_t) duk_lc_digits[cp & 0x0f];
24243 			} else {
24244 				q += duk_unicode_encode_xutf8(cp, q);
24245 			}
24246 		} else {
24247 			p++;  /* advance manually */
24248 			*q++ = (duk_uint8_t) DUK_ASC_QUESTION;
24249 		}
24250 		nchars++;
24251 	}
24252 	*q++ = (duk_uint8_t) DUK_ASC_SINGLEQUOTE;
24253 
24254 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (q - buf));
24255 }
24256 
duk__push_string_tval_readable(duk_hthread * thr,duk_tval * tv,duk_bool_t error_aware)24257 DUK_LOCAL const char *duk__push_string_tval_readable(duk_hthread *thr, duk_tval *tv, duk_bool_t error_aware) {
24258 	DUK_ASSERT_CTX_VALID(thr);
24259 	/* 'tv' may be NULL */
24260 
24261 	if (tv == NULL) {
24262 		duk_push_literal(thr, "none");
24263 	} else {
24264 		switch (DUK_TVAL_GET_TAG(tv)) {
24265 		case DUK_TAG_STRING: {
24266 			duk_hstring *h = DUK_TVAL_GET_STRING(tv);
24267 			if (DUK_HSTRING_HAS_SYMBOL(h)) {
24268 				/* XXX: string summary produces question marks
24269 				 * so this is not very ideal.
24270 				 */
24271 				duk_push_literal(thr, "[Symbol ");
24272 				duk_push_string(thr, duk__get_symbol_type_string(h));
24273 				duk_push_literal(thr, " ");
24274 				duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24275 				duk_push_literal(thr, "]");
24276 				duk_concat(thr, 5);
24277 				break;
24278 			}
24279 			duk__push_hstring_readable_unicode(thr, h, DUK__READABLE_STRING_MAXCHARS);
24280 			break;
24281 		}
24282 		case DUK_TAG_OBJECT: {
24283 			duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
24284 			DUK_ASSERT(h != NULL);
24285 
24286 			if (error_aware &&
24287 			    duk_hobject_prototype_chain_contains(thr, h, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
24288 				/* Get error message in a side effect free way if
24289 				 * possible; if not, summarize as a generic object.
24290 				 * Error message currently gets quoted.
24291 				 */
24292 				/* XXX: better internal getprop call; get without side effects
24293 				 * but traverse inheritance chain.
24294 				 */
24295 				duk_tval *tv_msg;
24296 				tv_msg = duk_hobject_find_existing_entry_tval_ptr(thr->heap, h, DUK_HTHREAD_STRING_MESSAGE(thr));
24297 				if (tv_msg != NULL && DUK_TVAL_IS_STRING(tv_msg)) {
24298 					/* It's critical to avoid recursion so
24299 					 * only summarize a string .message.
24300 					 */
24301 					duk__push_hstring_readable_unicode(thr, DUK_TVAL_GET_STRING(tv_msg), DUK__READABLE_ERRMSG_MAXCHARS);
24302 					break;
24303 				}
24304 			}
24305 			duk_push_class_string_tval(thr, tv, 1 /*avoid_side_effects*/);
24306 			break;
24307 		}
24308 		case DUK_TAG_BUFFER: {
24309 			/* While plain buffers mimic Uint8Arrays, they summarize differently.
24310 			 * This is useful so that the summarized string accurately reflects the
24311 			 * internal type which may matter for figuring out bugs etc.
24312 			 */
24313 			/* XXX: Hex encoded, length limited buffer summary here? */
24314 			duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv);
24315 			DUK_ASSERT(h != NULL);
24316 			duk_push_sprintf(thr, "[buffer:%ld]", (long) DUK_HBUFFER_GET_SIZE(h));
24317 			break;
24318 		}
24319 		case DUK_TAG_POINTER: {
24320 			/* Surround with parentheses like in JX, ensures NULL pointer
24321 			 * is distinguishable from null value ("(null)" vs "null").
24322 			 */
24323 			duk_push_tval(thr, tv);
24324 			duk_push_sprintf(thr, "(%s)", duk_to_string(thr, -1));
24325 			duk_remove_m2(thr);
24326 			break;
24327 		}
24328 		default: {
24329 			duk_push_tval(thr, tv);
24330 			break;
24331 		}
24332 		}
24333 	}
24334 
24335 	return duk_to_string(thr, -1);
24336 }
duk_push_string_tval_readable(duk_hthread * thr,duk_tval * tv)24337 DUK_INTERNAL const char *duk_push_string_tval_readable(duk_hthread *thr, duk_tval *tv) {
24338 	DUK_ASSERT_API_ENTRY(thr);
24339 	return duk__push_string_tval_readable(thr, tv, 0 /*error_aware*/);
24340 }
24341 
duk_push_string_readable(duk_hthread * thr,duk_idx_t idx)24342 DUK_INTERNAL const char *duk_push_string_readable(duk_hthread *thr, duk_idx_t idx) {
24343 	DUK_ASSERT_API_ENTRY(thr);
24344 	return duk_push_string_tval_readable(thr, duk_get_tval(thr, idx));
24345 }
24346 
duk_push_string_tval_readable_error(duk_hthread * thr,duk_tval * tv)24347 DUK_INTERNAL const char *duk_push_string_tval_readable_error(duk_hthread *thr, duk_tval *tv) {
24348 	DUK_ASSERT_API_ENTRY(thr);
24349 	return duk__push_string_tval_readable(thr, tv, 1 /*error_aware*/);
24350 }
24351 
duk_push_symbol_descriptive_string(duk_hthread * thr,duk_hstring * h)24352 DUK_INTERNAL void duk_push_symbol_descriptive_string(duk_hthread *thr, duk_hstring *h) {
24353 	const duk_uint8_t *p;
24354 	const duk_uint8_t *p_end;
24355 	const duk_uint8_t *q;
24356 
24357 	DUK_ASSERT_API_ENTRY(thr);
24358 
24359 	/* .toString() */
24360 	duk_push_literal(thr, "Symbol(");
24361 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
24362 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
24363 	DUK_ASSERT(p[0] == 0xff || (p[0] & 0xc0) == 0x80);
24364 	p++;
24365 	for (q = p; q < p_end; q++) {
24366 		if (*q == 0xffU) {
24367 			/* Terminate either at end-of-string (but NUL MUST
24368 			 * be accepted without terminating description) or
24369 			 * 0xFF, which is used to mark start of unique trailer
24370 			 * (and cannot occur in CESU-8 / extended UTF-8).
24371 			 */
24372 			break;
24373 		}
24374 	}
24375 	duk_push_lstring(thr, (const char *) p, (duk_size_t) (q - p));
24376 	duk_push_literal(thr, ")");
24377 	duk_concat(thr, 3);
24378 }
24379 
24380 /*
24381  *  Functions
24382  */
24383 
24384 #if 0  /* not used yet */
24385 DUK_INTERNAL void duk_push_hnatfunc_name(duk_hthread *thr, duk_hnatfunc *h) {
24386 	duk_c_function func;
24387 
24388 	DUK_ASSERT_API_ENTRY(thr);
24389 	DUK_ASSERT(h != NULL);
24390 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h));
24391 
24392 	duk_push_sprintf(thr, "native_");
24393 	func = h->func;
24394 	duk_push_string_funcptr(thr, (duk_uint8_t *) &func, sizeof(func));
24395 	duk_push_sprintf(thr, "_%04x_%04x",
24396 	                 (unsigned int) (duk_uint16_t) h->nargs,
24397 	                 (unsigned int) (duk_uint16_t) h->magic);
24398 	duk_concat(thr, 3);
24399 }
24400 #endif
24401 
24402 /*
24403  *  duk_tval slice copy
24404  */
24405 
duk_copy_tvals_incref(duk_hthread * thr,duk_tval * tv_dst,duk_tval * tv_src,duk_size_t count)24406 DUK_INTERNAL void duk_copy_tvals_incref(duk_hthread *thr, duk_tval *tv_dst, duk_tval *tv_src, duk_size_t count) {
24407 	duk_tval *tv;
24408 
24409 	DUK_ASSERT_API_ENTRY(thr);
24410 	DUK_UNREF(thr);
24411 	DUK_ASSERT(count * sizeof(duk_tval) >= count);  /* no wrap */
24412 
24413 	duk_memcpy_unsafe((void *) tv_dst, (const void *) tv_src, count * sizeof(duk_tval));
24414 
24415 	tv = tv_dst;
24416 	while (count-- > 0) {
24417 		DUK_TVAL_INCREF(thr, tv);
24418 		tv++;
24419 	}
24420 }
24421 
24422 /* automatic undefs */
24423 #undef DUK__ASSERT_SPACE
24424 #undef DUK__CHECK_SPACE
24425 #undef DUK__ERROR_STASH_SHARED
24426 #undef DUK__PACK_ARGS
24427 #undef DUK__READABLE_ERRMSG_MAXCHARS
24428 #undef DUK__READABLE_STRING_MAXCHARS
24429 #undef DUK__READABLE_SUMMARY_MAXCHARS
24430 #line 1 "duk_api_string.c"
24431 /*
24432  *  String manipulation
24433  */
24434 
24435 /* #include duk_internal.h -> already included */
24436 
duk__concat_and_join_helper(duk_hthread * thr,duk_idx_t count_in,duk_bool_t is_join)24437 DUK_LOCAL void duk__concat_and_join_helper(duk_hthread *thr, duk_idx_t count_in, duk_bool_t is_join) {
24438 	duk_uint_t count;
24439 	duk_uint_t i;
24440 	duk_size_t idx;
24441 	duk_size_t len;
24442 	duk_hstring *h;
24443 	duk_uint8_t *buf;
24444 
24445 	DUK_ASSERT_CTX_VALID(thr);
24446 
24447 	if (DUK_UNLIKELY(count_in <= 0)) {
24448 		if (count_in < 0) {
24449 			DUK_ERROR_RANGE_INVALID_COUNT(thr);
24450 			DUK_WO_NORETURN(return;);
24451 		}
24452 		DUK_ASSERT(count_in == 0);
24453 		duk_push_hstring_empty(thr);
24454 		return;
24455 	}
24456 	count = (duk_uint_t) count_in;
24457 
24458 	if (is_join) {
24459 		duk_size_t t1, t2, limit;
24460 		h = duk_to_hstring(thr, -((duk_idx_t) count) - 1);
24461 		DUK_ASSERT(h != NULL);
24462 
24463 		/* A bit tricky overflow test, see doc/code-issues.rst. */
24464 		t1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24465 		t2 = (duk_size_t) (count - 1);
24466 		limit = (duk_size_t) DUK_HSTRING_MAX_BYTELEN;
24467 		if (DUK_UNLIKELY(t2 != 0 && t1 > limit / t2)) {
24468 			/* Combined size of separators already overflows. */
24469 			goto error_overflow;
24470 		}
24471 		len = (duk_size_t) (t1 * t2);
24472 	} else {
24473 		len = (duk_size_t) 0;
24474 	}
24475 
24476 	for (i = count; i >= 1; i--) {
24477 		duk_size_t new_len;
24478 		h = duk_to_hstring(thr, -((duk_idx_t) i));
24479 		new_len = len + (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
24480 
24481 		/* Impose a string maximum length, need to handle overflow
24482 		 * correctly.
24483 		 */
24484 		if (new_len < len ||  /* wrapped */
24485 		    new_len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN) {
24486 			goto error_overflow;
24487 		}
24488 		len = new_len;
24489 	}
24490 
24491 	DUK_DDD(DUK_DDDPRINT("join/concat %lu strings, total length %lu bytes",
24492 	                     (unsigned long) count, (unsigned long) len));
24493 
24494 	/* Use stack allocated buffer to ensure reachability in errors
24495 	 * (e.g. intern error).
24496 	 */
24497 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24498 	DUK_ASSERT(buf != NULL);
24499 
24500 	/* [ ... (sep) str1 str2 ... strN buf ] */
24501 
24502 	idx = 0;
24503 	for (i = count; i >= 1; i--) {
24504 		if (is_join && i != count) {
24505 			h = duk_require_hstring(thr, -((duk_idx_t) count) - 2);  /* extra -1 for buffer */
24506 			duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24507 			idx += DUK_HSTRING_GET_BYTELEN(h);
24508 		}
24509 		h = duk_require_hstring(thr, -((duk_idx_t) i) - 1);  /* extra -1 for buffer */
24510 		duk_memcpy(buf + idx, DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
24511 		idx += DUK_HSTRING_GET_BYTELEN(h);
24512 	}
24513 
24514 	DUK_ASSERT(idx == len);
24515 
24516 	/* [ ... (sep) str1 str2 ... strN buf ] */
24517 
24518 	/* Get rid of the strings early to minimize memory use before intern. */
24519 
24520 	if (is_join) {
24521 		duk_replace(thr, -((duk_idx_t) count) - 2);  /* overwrite sep */
24522 		duk_pop_n(thr, (duk_idx_t) count);
24523 	} else {
24524 		duk_replace(thr, -((duk_idx_t) count) - 1);  /* overwrite str1 */
24525 		duk_pop_n(thr, (duk_idx_t) (count - 1));
24526 	}
24527 
24528 	/* [ ... buf ] */
24529 
24530 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24531 
24532 	/* [ ... res ] */
24533 	return;
24534 
24535  error_overflow:
24536 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24537 	DUK_WO_NORETURN(return;);
24538 }
24539 
duk_concat(duk_hthread * thr,duk_idx_t count)24540 DUK_EXTERNAL void duk_concat(duk_hthread *thr, duk_idx_t count) {
24541 	DUK_ASSERT_API_ENTRY(thr);
24542 
24543 	duk__concat_and_join_helper(thr, count, 0 /*is_join*/);
24544 }
24545 
24546 #if defined(DUK_USE_PREFER_SIZE)
duk_concat_2(duk_hthread * thr)24547 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24548 	DUK_ASSERT_API_ENTRY(thr);
24549 	duk_concat(thr, 2);
24550 }
24551 #else  /* DUK_USE_PREFER_SIZE */
duk_concat_2(duk_hthread * thr)24552 DUK_INTERNAL void duk_concat_2(duk_hthread *thr) {
24553 	duk_hstring *h1;
24554 	duk_hstring *h2;
24555 	duk_uint8_t *buf;
24556 	duk_size_t len1;
24557 	duk_size_t len2;
24558 	duk_size_t len;
24559 
24560 	DUK_ASSERT_API_ENTRY(thr);
24561 	DUK_ASSERT(duk_get_top(thr) >= 2);  /* Trusted caller. */
24562 
24563 	h1 = duk_to_hstring(thr, -2);
24564 	h2 = duk_to_hstring(thr, -1);
24565 	len1 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
24566 	len2 = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
24567 	len = len1 + len2;
24568 	if (DUK_UNLIKELY(len < len1 ||  /* wrapped */
24569 	                 len > (duk_size_t) DUK_HSTRING_MAX_BYTELEN)) {
24570 		goto error_overflow;
24571 	}
24572 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, len);
24573 	DUK_ASSERT(buf != NULL);
24574 
24575 	duk_memcpy((void *) buf, (const void *) DUK_HSTRING_GET_DATA(h1), (size_t) len1);
24576 	duk_memcpy((void *) (buf + len1), (const void *) DUK_HSTRING_GET_DATA(h2), (size_t) len2);
24577 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
24578 
24579 	/* [ ... str1 str2 buf ] */
24580 
24581 	duk_replace(thr, -3);
24582 	duk_pop_unsafe(thr);
24583 	return;
24584 
24585  error_overflow:
24586 	DUK_ERROR_RANGE(thr, DUK_STR_RESULT_TOO_LONG);
24587 	DUK_WO_NORETURN(return;);
24588 }
24589 #endif  /* DUK_USE_PREFER_SIZE */
24590 
duk_join(duk_hthread * thr,duk_idx_t count)24591 DUK_EXTERNAL void duk_join(duk_hthread *thr, duk_idx_t count) {
24592 	DUK_ASSERT_API_ENTRY(thr);
24593 
24594 	duk__concat_and_join_helper(thr, count, 1 /*is_join*/);
24595 }
24596 
24597 /* XXX: could map/decode be unified with duk_unicode_support.c code?
24598  * Case conversion needs also the character surroundings though.
24599  */
24600 
duk_decode_string(duk_hthread * thr,duk_idx_t idx,duk_decode_char_function callback,void * udata)24601 DUK_EXTERNAL void duk_decode_string(duk_hthread *thr, duk_idx_t idx, duk_decode_char_function callback, void *udata) {
24602 	duk_hstring *h_input;
24603 	const duk_uint8_t *p, *p_start, *p_end;
24604 	duk_codepoint_t cp;
24605 
24606 	DUK_ASSERT_API_ENTRY(thr);
24607 
24608 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24609 	DUK_ASSERT(h_input != NULL);
24610 
24611 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24612 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24613 	p = p_start;
24614 
24615 	for (;;) {
24616 		if (p >= p_end) {
24617 			break;
24618 		}
24619 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24620 		callback(udata, cp);
24621 	}
24622 }
24623 
duk_map_string(duk_hthread * thr,duk_idx_t idx,duk_map_char_function callback,void * udata)24624 DUK_EXTERNAL void duk_map_string(duk_hthread *thr, duk_idx_t idx, duk_map_char_function callback, void *udata) {
24625 	duk_hstring *h_input;
24626 	duk_bufwriter_ctx bw_alloc;
24627 	duk_bufwriter_ctx *bw;
24628 	const duk_uint8_t *p, *p_start, *p_end;
24629 	duk_codepoint_t cp;
24630 
24631 	DUK_ASSERT_API_ENTRY(thr);
24632 
24633 	idx = duk_normalize_index(thr, idx);
24634 
24635 	h_input = duk_require_hstring(thr, idx);  /* Accept symbols. */
24636 	DUK_ASSERT(h_input != NULL);
24637 
24638 	bw = &bw_alloc;
24639 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* Reasonable output estimate. */
24640 
24641 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
24642 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
24643 	p = p_start;
24644 
24645 	for (;;) {
24646 		/* XXX: could write output in chunks with fewer ensure calls,
24647 		 * but relative benefit would be small here.
24648 		 */
24649 
24650 		if (p >= p_end) {
24651 			break;
24652 		}
24653 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p, p_start, p_end);
24654 		cp = callback(udata, cp);
24655 
24656 		DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
24657 	}
24658 
24659 	DUK_BW_COMPACT(thr, bw);
24660 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 encoded. */
24661 	duk_replace(thr, idx);
24662 }
24663 
duk_substring(duk_hthread * thr,duk_idx_t idx,duk_size_t start_offset,duk_size_t end_offset)24664 DUK_EXTERNAL void duk_substring(duk_hthread *thr, duk_idx_t idx, duk_size_t start_offset, duk_size_t end_offset) {
24665 	duk_hstring *h;
24666 	duk_hstring *res;
24667 	duk_size_t start_byte_offset;
24668 	duk_size_t end_byte_offset;
24669 	duk_size_t charlen;
24670 
24671 	DUK_ASSERT_API_ENTRY(thr);
24672 
24673 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24674 	h = duk_require_hstring(thr, idx);
24675 	DUK_ASSERT(h != NULL);
24676 
24677 	charlen = DUK_HSTRING_GET_CHARLEN(h);
24678 	if (end_offset >= charlen) {
24679 		end_offset = charlen;
24680 	}
24681 	if (start_offset > end_offset) {
24682 		start_offset = end_offset;
24683 	}
24684 
24685 	DUK_ASSERT_DISABLE(start_offset >= 0);
24686 	DUK_ASSERT(start_offset <= end_offset && start_offset <= DUK_HSTRING_GET_CHARLEN(h));
24687 	DUK_ASSERT_DISABLE(end_offset >= 0);
24688 	DUK_ASSERT(end_offset >= start_offset && end_offset <= DUK_HSTRING_GET_CHARLEN(h));
24689 
24690 	/* Guaranteed by string limits. */
24691 	DUK_ASSERT(start_offset <= DUK_UINT32_MAX);
24692 	DUK_ASSERT(end_offset <= DUK_UINT32_MAX);
24693 
24694 	start_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) start_offset);
24695 	end_byte_offset = (duk_size_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) end_offset);
24696 
24697 	DUK_ASSERT(end_byte_offset >= start_byte_offset);
24698 	DUK_ASSERT(end_byte_offset - start_byte_offset <= DUK_UINT32_MAX);  /* Guaranteed by string limits. */
24699 
24700 	/* No size check is necessary. */
24701 	res = duk_heap_strtable_intern_checked(thr,
24702 	                                       DUK_HSTRING_GET_DATA(h) + start_byte_offset,
24703 	                                       (duk_uint32_t) (end_byte_offset - start_byte_offset));
24704 
24705 	duk_push_hstring(thr, res);
24706 	duk_replace(thr, idx);
24707 }
24708 
24709 /* XXX: this is quite clunky.  Add Unicode helpers to scan backwards and
24710  * forwards with a callback to process codepoints?
24711  */
duk_trim(duk_hthread * thr,duk_idx_t idx)24712 DUK_EXTERNAL void duk_trim(duk_hthread *thr, duk_idx_t idx) {
24713 	duk_hstring *h;
24714 	const duk_uint8_t *p, *p_start, *p_end, *p_tmp1, *p_tmp2;  /* pointers for scanning */
24715 	const duk_uint8_t *q_start, *q_end;  /* start (incl) and end (excl) of trimmed part */
24716 	duk_codepoint_t cp;
24717 
24718 	DUK_ASSERT_API_ENTRY(thr);
24719 
24720 	idx = duk_require_normalize_index(thr, idx);  /* Accept symbols. */
24721 	h = duk_require_hstring(thr, idx);
24722 	DUK_ASSERT(h != NULL);
24723 
24724 	p_start = DUK_HSTRING_GET_DATA(h);
24725 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
24726 
24727 	p = p_start;
24728 	while (p < p_end) {
24729 		p_tmp1 = p;
24730 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp1, p_start, p_end);
24731 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24732 			break;
24733 		}
24734 		p = p_tmp1;
24735 	}
24736 	q_start = p;
24737 	if (p == p_end) {
24738 		/* Entire string is whitespace. */
24739 		q_end = p;
24740 		goto scan_done;
24741 	}
24742 
24743 	p = p_end;
24744 	while (p > p_start) {
24745 		p_tmp1 = p;
24746 		while (p > p_start) {
24747 			p--;
24748 			if (((*p) & 0xc0) != 0x80) {
24749 				break;
24750 			}
24751 		}
24752 		p_tmp2 = p;
24753 
24754 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &p_tmp2, p_start, p_end);
24755 		if (!(duk_unicode_is_whitespace(cp) || duk_unicode_is_line_terminator(cp))) {
24756 			p = p_tmp1;
24757 			break;
24758 		}
24759 	}
24760 	q_end = p;
24761 
24762  scan_done:
24763 	/* This may happen when forward and backward scanning disagree
24764 	 * (possible for non-extended-UTF-8 strings).
24765 	 */
24766 	if (q_end < q_start) {
24767 		q_end = q_start;
24768 	}
24769 
24770 	DUK_ASSERT(q_start >= p_start && q_start <= p_end);
24771 	DUK_ASSERT(q_end >= p_start && q_end <= p_end);
24772 	DUK_ASSERT(q_end >= q_start);
24773 
24774 	DUK_DDD(DUK_DDDPRINT("trim: p_start=%p, p_end=%p, q_start=%p, q_end=%p",
24775 	                     (const void *) p_start, (const void *) p_end,
24776 	                     (const void *) q_start, (const void *) q_end));
24777 
24778 	if (q_start == p_start && q_end == p_end) {
24779 		DUK_DDD(DUK_DDDPRINT("nothing was trimmed: avoid interning (hashing etc)"));
24780 		return;
24781 	}
24782 
24783 	duk_push_lstring(thr, (const char *) q_start, (duk_size_t) (q_end - q_start));
24784 	duk_replace(thr, idx);
24785 }
24786 
duk_char_code_at(duk_hthread * thr,duk_idx_t idx,duk_size_t char_offset)24787 DUK_EXTERNAL duk_codepoint_t duk_char_code_at(duk_hthread *thr, duk_idx_t idx, duk_size_t char_offset) {
24788 	duk_hstring *h;
24789 	duk_ucodepoint_t cp;
24790 
24791 	DUK_ASSERT_API_ENTRY(thr);
24792 
24793 	/* XXX: Share code with String.prototype.charCodeAt?  Main difference
24794 	 * is handling of clamped offsets.
24795 	 */
24796 
24797 	h = duk_require_hstring(thr, idx);  /* Accept symbols. */
24798 	DUK_ASSERT(h != NULL);
24799 
24800 	DUK_ASSERT_DISABLE(char_offset >= 0);  /* Always true, arg is unsigned. */
24801 	if (char_offset >= DUK_HSTRING_GET_CHARLEN(h)) {
24802 		return 0;
24803 	}
24804 
24805 	DUK_ASSERT(char_offset <= DUK_UINT_MAX);  /* Guaranteed by string limits. */
24806 	cp = duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) char_offset, 0 /*surrogate_aware*/);
24807 	return (duk_codepoint_t) cp;
24808 }
24809 #line 1 "duk_api_time.c"
24810 /*
24811  *  Date/time.
24812  */
24813 
24814 /* #include duk_internal.h -> already included */
24815 
duk_time_get_ecmascript_time(duk_hthread * thr)24816 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time(duk_hthread *thr) {
24817 	/* ECMAScript time, with millisecond fractions.  Exposed via
24818 	 * duk_get_now() for example.
24819 	 */
24820 	DUK_UNREF(thr);
24821 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24822 }
24823 
duk_time_get_ecmascript_time_nofrac(duk_hthread * thr)24824 DUK_INTERNAL duk_double_t duk_time_get_ecmascript_time_nofrac(duk_hthread *thr) {
24825 	/* ECMAScript time without millisecond fractions.  Exposed via
24826 	 * the Date built-in which doesn't allow fractions.
24827 	 */
24828 	DUK_UNREF(thr);
24829 	return (duk_double_t) DUK_FLOOR(DUK_USE_DATE_GET_NOW(thr));
24830 }
24831 
duk_time_get_monotonic_time(duk_hthread * thr)24832 DUK_INTERNAL duk_double_t duk_time_get_monotonic_time(duk_hthread *thr) {
24833 	DUK_UNREF(thr);
24834 #if defined(DUK_USE_GET_MONOTONIC_TIME)
24835 	return (duk_double_t) DUK_USE_GET_MONOTONIC_TIME(thr);
24836 #else
24837 	return (duk_double_t) DUK_USE_DATE_GET_NOW(thr);
24838 #endif
24839 }
24840 
duk_get_now(duk_hthread * thr)24841 DUK_EXTERNAL duk_double_t duk_get_now(duk_hthread *thr) {
24842 	DUK_ASSERT_API_ENTRY(thr);
24843 	DUK_UNREF(thr);
24844 
24845 	/* This API intentionally allows millisecond fractions. */
24846 	return duk_time_get_ecmascript_time(thr);
24847 }
24848 
24849 #if 0  /* XXX: worth exposing? */
24850 DUK_EXTERNAL duk_double_t duk_get_monotonic_time(duk_hthread *thr) {
24851 	DUK_ASSERT_API_ENTRY(thr);
24852 	DUK_UNREF(thr);
24853 
24854 	return duk_time_get_monotonic_time(thr);
24855 }
24856 #endif
24857 
duk_time_to_components(duk_hthread * thr,duk_double_t timeval,duk_time_components * comp)24858 DUK_EXTERNAL void duk_time_to_components(duk_hthread *thr, duk_double_t timeval, duk_time_components *comp) {
24859 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
24860 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
24861 	duk_uint_t flags;
24862 
24863 	DUK_ASSERT_API_ENTRY(thr);
24864 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
24865 	DUK_UNREF(thr);
24866 
24867 	/* Convert as one-based, but change month to zero-based to match the
24868 	 * ECMAScript Date built-in behavior 1:1.
24869 	 */
24870 	flags = DUK_DATE_FLAG_ONEBASED | DUK_DATE_FLAG_NAN_TO_ZERO;
24871 
24872 	duk_bi_date_timeval_to_parts(timeval, parts, dparts, flags);
24873 
24874 	/* XXX: sub-millisecond accuracy for the API */
24875 
24876 	DUK_ASSERT(dparts[DUK_DATE_IDX_MONTH] >= 1.0 && dparts[DUK_DATE_IDX_MONTH] <= 12.0);
24877 	comp->year = dparts[DUK_DATE_IDX_YEAR];
24878 	comp->month = dparts[DUK_DATE_IDX_MONTH] - 1.0;
24879 	comp->day = dparts[DUK_DATE_IDX_DAY];
24880 	comp->hours = dparts[DUK_DATE_IDX_HOUR];
24881 	comp->minutes = dparts[DUK_DATE_IDX_MINUTE];
24882 	comp->seconds = dparts[DUK_DATE_IDX_SECOND];
24883 	comp->milliseconds = dparts[DUK_DATE_IDX_MILLISECOND];
24884 	comp->weekday = dparts[DUK_DATE_IDX_WEEKDAY];
24885 }
24886 
duk_components_to_time(duk_hthread * thr,duk_time_components * comp)24887 DUK_EXTERNAL duk_double_t duk_components_to_time(duk_hthread *thr, duk_time_components *comp) {
24888 	duk_double_t d;
24889 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
24890 	duk_uint_t flags;
24891 
24892 	DUK_ASSERT_API_ENTRY(thr);
24893 	DUK_ASSERT(comp != NULL);  /* XXX: or check? */
24894 	DUK_UNREF(thr);
24895 
24896 	/* Match Date constructor behavior (with UTC time).  Month is given
24897 	 * as zero-based.  Day-of-month is given as one-based so normalize
24898 	 * it to zero-based as the internal conversion helpers expects all
24899 	 * components to be zero-based.
24900 	 */
24901 	flags = 0;
24902 
24903 	/* XXX: expensive conversion; use array format in API instead, or unify
24904 	 * time provider and time API to use same struct?
24905 	 */
24906 
24907 	dparts[DUK_DATE_IDX_YEAR] = comp->year;
24908 	dparts[DUK_DATE_IDX_MONTH] = comp->month;
24909 	dparts[DUK_DATE_IDX_DAY] = comp->day - 1.0;
24910 	dparts[DUK_DATE_IDX_HOUR] = comp->hours;
24911 	dparts[DUK_DATE_IDX_MINUTE] = comp->minutes;
24912 	dparts[DUK_DATE_IDX_SECOND] = comp->seconds;
24913 	dparts[DUK_DATE_IDX_MILLISECOND] = comp->milliseconds;
24914 	dparts[DUK_DATE_IDX_WEEKDAY] = 0;  /* ignored */
24915 
24916 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
24917 
24918 	return d;
24919 }
24920 #line 1 "duk_bi_array.c"
24921 /*
24922  *  Array built-ins
24923  *
24924  *  Most Array built-ins are intentionally generic in ECMAScript, and are
24925  *  intended to work even when the 'this' binding is not an Array instance.
24926  *  This ECMAScript feature is also used by much real world code.  For this
24927  *  reason the implementations here don't assume exotic Array behavior or
24928  *  e.g. presence of a .length property.  However, some algorithms have a
24929  *  fast path for duk_harray backed actual Array instances, enabled when
24930  *  footprint is not a concern.
24931  *
24932  *  XXX: the "Throw" flag should be set for (almost?) all [[Put]] and
24933  *  [[Delete]] operations, but it's currently false throughout.  Go through
24934  *  all put/delete cases and check throw flag use.  Need a new API primitive
24935  *  which allows throws flag to be specified.
24936  *
24937  *  XXX: array lengths above 2G won't work reliably.  There are many places
24938  *  where one needs a full signed 32-bit range ([-0xffffffff, 0xffffffff],
24939  *  i.e. -33- bits).  Although array 'length' cannot be written to be outside
24940  *  the unsigned 32-bit range (E5.1 Section 15.4.5.1 throws a RangeError if so)
24941  *  some intermediate values may be above 0xffffffff and this may not be always
24942  *  correctly handled now (duk_uint32_t is not enough for all algorithms).
24943  *  For instance, push() can legitimately write entries beyond length 0xffffffff
24944  *  and cause a RangeError only at the end.  To do this properly, the current
24945  *  push() implementation tracks the array index using a 'double' instead of a
24946  *  duk_uint32_t (which is somewhat awkward).  See test-bi-array-push-maxlen.js.
24947  *
24948  *  On using "put" vs. "def" prop
24949  *  =============================
24950  *
24951  *  Code below must be careful to use the appropriate primitive as it matters
24952  *  for compliance.  When using "put" there may be inherited properties in
24953  *  Array.prototype which cause side effects when values are written.  When
24954  *  using "define" there are no such side effects, and many test262 test cases
24955  *  check for this (for real world code, such side effects are very rare).
24956  *  Both "put" and "define" are used in the E5.1 specification; as a rule,
24957  *  "put" is used when modifying an existing array (or a non-array 'this'
24958  *  binding) and "define" for setting values into a fresh result array.
24959  */
24960 
24961 /* #include duk_internal.h -> already included */
24962 
24963 /* Perform an intermediate join when this many elements have been pushed
24964  * on the value stack.
24965  */
24966 #define  DUK__ARRAY_MID_JOIN_LIMIT  4096
24967 
24968 #if defined(DUK_USE_ARRAY_BUILTIN)
24969 
24970 /*
24971  *  Shared helpers.
24972  */
24973 
24974 /* Shared entry code for many Array built-ins: the 'this' binding is pushed
24975  * on the value stack and object coerced, and the current .length is returned.
24976  * Note that length is left on stack (it could be popped, but that's not
24977  * usually necessary because call handling will clean it up automatically).
24978  */
duk__push_this_obj_len_u32(duk_hthread * thr)24979 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_hthread *thr) {
24980 	duk_uint32_t len;
24981 
24982 	/* XXX: push more directly? */
24983 	(void) duk_push_this_coercible_to_object(thr);
24984 	DUK_ASSERT_HOBJECT_VALID(duk_get_hobject(thr, -1));
24985 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_LENGTH);
24986 	len = duk_to_uint32(thr, -1);
24987 
24988 	/* -> [ ... ToObject(this) ToUint32(length) ] */
24989 	return len;
24990 }
24991 
duk__push_this_obj_len_u32_limited(duk_hthread * thr)24992 DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32_limited(duk_hthread *thr) {
24993 	/* Range limited to [0, 0x7fffffff] range, i.e. range that can be
24994 	 * represented with duk_int32_t.  Use this when the method doesn't
24995 	 * handle the full 32-bit unsigned range correctly.
24996 	 */
24997 	duk_uint32_t ret = duk__push_this_obj_len_u32(thr);
24998 	if (DUK_UNLIKELY(ret >= 0x80000000UL)) {
24999 		DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25000 		DUK_WO_NORETURN(return 0U;);
25001 	}
25002 	return ret;
25003 }
25004 
25005 #if defined(DUK_USE_ARRAY_FASTPATH)
25006 /* Check if 'this' binding is an Array instance (duk_harray) which satisfies
25007  * a few other guarantees for fast path operation.  The fast path doesn't
25008  * need to handle all operations, even for duk_harrays, but must handle a
25009  * significant fraction to improve performance.  Return a non-NULL duk_harray
25010  * pointer when all fast path criteria are met, NULL otherwise.
25011  */
duk__arraypart_fastpath_this(duk_hthread * thr)25012 DUK_LOCAL duk_harray *duk__arraypart_fastpath_this(duk_hthread *thr) {
25013 	duk_tval *tv;
25014 	duk_hobject *h;
25015 	duk_uint_t flags_mask, flags_bits, flags_value;
25016 
25017 	DUK_ASSERT(thr->valstack_bottom > thr->valstack);  /* because call in progress */
25018 	tv = DUK_GET_THIS_TVAL_PTR(thr);
25019 
25020 	/* Fast path requires that 'this' is a duk_harray.  Read only arrays
25021 	 * (ROM backed) are also rejected for simplicity.
25022 	 */
25023 	if (!DUK_TVAL_IS_OBJECT(tv)) {
25024 		DUK_DD(DUK_DDPRINT("reject array fast path: not an object"));
25025 		return NULL;
25026 	}
25027 	h = DUK_TVAL_GET_OBJECT(tv);
25028 	DUK_ASSERT(h != NULL);
25029 	flags_mask = DUK_HOBJECT_FLAG_ARRAY_PART | \
25030 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY | \
25031 	             DUK_HEAPHDR_FLAG_READONLY;
25032 	flags_bits = DUK_HOBJECT_FLAG_ARRAY_PART | \
25033 	             DUK_HOBJECT_FLAG_EXOTIC_ARRAY;
25034 	flags_value = DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) h);
25035 	if ((flags_value & flags_mask) != flags_bits) {
25036 		DUK_DD(DUK_DDPRINT("reject array fast path: object flag check failed"));
25037 		return NULL;
25038 	}
25039 
25040 	/* In some cases a duk_harray's 'length' may be larger than the
25041 	 * current array part allocation.  Avoid the fast path in these
25042 	 * cases, so that all fast path code can safely assume that all
25043 	 * items in the range [0,length[ are backed by the current array
25044 	 * part allocation.
25045 	 */
25046 	if (((duk_harray *) h)->length > DUK_HOBJECT_GET_ASIZE(h)) {
25047 		DUK_DD(DUK_DDPRINT("reject array fast path: length > array part size"));
25048 		return NULL;
25049 	}
25050 
25051 	/* Guarantees for fast path. */
25052 	DUK_ASSERT(h != NULL);
25053 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0 || DUK_HOBJECT_A_GET_BASE(thr->heap, h) != NULL);
25054 	DUK_ASSERT(((duk_harray *) h)->length <= DUK_HOBJECT_GET_ASIZE(h));
25055 
25056 	DUK_DD(DUK_DDPRINT("array fast path allowed for: %!O", (duk_heaphdr *) h));
25057 	return (duk_harray *) h;
25058 }
25059 #endif  /* DUK_USE_ARRAY_FASTPATH */
25060 
25061 /*
25062  *  Constructor
25063  */
25064 
duk_bi_array_constructor(duk_hthread * thr)25065 DUK_INTERNAL duk_ret_t duk_bi_array_constructor(duk_hthread *thr) {
25066 	duk_idx_t nargs;
25067 	duk_harray *a;
25068 	duk_double_t d;
25069 	duk_uint32_t len;
25070 	duk_uint32_t len_prealloc;
25071 
25072 	nargs = duk_get_top(thr);
25073 
25074 	if (nargs == 1 && duk_is_number(thr, 0)) {
25075 		/* XXX: expensive check (also shared elsewhere - so add a shared internal API call?) */
25076 		d = duk_get_number(thr, 0);
25077 		len = duk_to_uint32(thr, 0);
25078 		if (((duk_double_t) len) != d) {
25079 			DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25080 		}
25081 
25082 		/* For small lengths create a dense preallocated array.
25083 		 * For large arrays preallocate an initial part.
25084 		 */
25085 		len_prealloc = len < 64 ? len : 64;
25086 		a = duk_push_harray_with_size(thr, len_prealloc);
25087 		DUK_ASSERT(a != NULL);
25088 		a->length = len;
25089 		return 1;
25090 	}
25091 
25092 	duk_pack(thr, nargs);
25093 	return 1;
25094 }
25095 
25096 /*
25097  *  isArray()
25098  */
25099 
duk_bi_array_constructor_is_array(duk_hthread * thr)25100 DUK_INTERNAL duk_ret_t duk_bi_array_constructor_is_array(duk_hthread *thr) {
25101 	duk_hobject *h;
25102 
25103 	h = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_ARRAY);
25104 	duk_push_boolean(thr, (h != NULL));
25105 	return 1;
25106 }
25107 
25108 /*
25109  *  toString()
25110  */
25111 
duk_bi_array_prototype_to_string(duk_hthread * thr)25112 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_hthread *thr) {
25113 	(void) duk_push_this_coercible_to_object(thr);
25114 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_JOIN);
25115 
25116 	/* [ ... this func ] */
25117 	if (!duk_is_callable(thr, -1)) {
25118 		/* Fall back to the initial (original) Object.toString().  We don't
25119 		 * currently have pointers to the built-in functions, only the top
25120 		 * level global objects (like "Array") so this is now done in a bit
25121 		 * of a hacky manner.  It would be cleaner to push the (original)
25122 		 * function and use duk_call_method().
25123 		 */
25124 
25125 		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
25126 		 * but should have no visible side effects.
25127 		 */
25128 		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
25129 		duk_set_top(thr, 0);
25130 		return duk_bi_object_prototype_to_string(thr);  /* has access to 'this' binding */
25131 	}
25132 
25133 	/* [ ... this func ] */
25134 
25135 	duk_insert(thr, -2);
25136 
25137 	/* [ ... func this ] */
25138 
25139 	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
25140 	                     (duk_tval *) duk_get_tval(thr, -2),
25141 	                     (duk_tval *) duk_get_tval(thr, -1)));
25142 	duk_call_method(thr, 0);
25143 
25144 	return 1;
25145 }
25146 
25147 /*
25148  *  concat()
25149  */
25150 
duk_bi_array_prototype_concat(duk_hthread * thr)25151 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_hthread *thr) {
25152 	duk_idx_t i, n;
25153 	duk_uint32_t j, idx, len;
25154 	duk_hobject *h;
25155 	duk_size_t tmp_len;
25156 
25157 	/* XXX: In ES2015 Array .length can be up to 2^53-1.  The current
25158 	 * implementation is limited to 2^32-1.
25159 	 */
25160 
25161 	/* XXX: Fast path for array 'this' and array element. */
25162 
25163 	/* XXX: The insert here is a bit expensive if there are a lot of items.
25164 	 * It could also be special cased in the outermost for loop quite easily
25165 	 * (as the element is dup()'d anyway).
25166 	 */
25167 
25168 	(void) duk_push_this_coercible_to_object(thr);
25169 	duk_insert(thr, 0);
25170 	n = duk_get_top(thr);
25171 	duk_push_array(thr);  /* -> [ ToObject(this) item1 ... itemN arr ] */
25172 
25173 	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
25174 	 * (which differs from the official algorithm).  If no error is thrown, this
25175 	 * doesn't matter as the length is updated at the end.  However, if an error
25176 	 * is thrown, the length will be unset.  That shouldn't matter because the
25177 	 * caller won't get a reference to the intermediate value.
25178 	 */
25179 
25180 	idx = 0;
25181 	for (i = 0; i < n; i++) {
25182 		duk_bool_t spreadable;
25183 		duk_bool_t need_has_check;
25184 
25185 		DUK_ASSERT_TOP(thr, n + 1);
25186 
25187 		/* [ ToObject(this) item1 ... itemN arr ] */
25188 
25189 		h = duk_get_hobject(thr, i);
25190 
25191 		if (h == NULL) {
25192 			spreadable = 0;
25193 		} else {
25194 #if defined(DUK_USE_SYMBOL_BUILTIN)
25195 			duk_get_prop_stridx(thr, i, DUK_STRIDX_WELLKNOWN_SYMBOL_IS_CONCAT_SPREADABLE);
25196 			if (duk_is_undefined(thr, -1)) {
25197 				spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25198 			} else {
25199 				spreadable = duk_to_boolean(thr, -1);
25200 			}
25201 			duk_pop_nodecref_unsafe(thr);
25202 #else
25203 			spreadable = (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY);
25204 #endif
25205 		}
25206 
25207 		if (!spreadable) {
25208 			duk_dup(thr, i);
25209 			duk_xdef_prop_index_wec(thr, -2, idx);
25210 			idx++;
25211 			if (DUK_UNLIKELY(idx == 0U)) {
25212 				/* Index after update is 0, and index written
25213 				 * was 0xffffffffUL which is no longer a valid
25214 				 * array index.
25215 				 */
25216 				goto fail_wrap;
25217 			}
25218 			continue;
25219 		}
25220 
25221 		DUK_ASSERT(duk_is_object(thr, i));
25222 		need_has_check = (DUK_HOBJECT_IS_PROXY(h) != 0);  /* Always 0 w/o Proxy support. */
25223 
25224 		/* [ ToObject(this) item1 ... itemN arr ] */
25225 
25226 		tmp_len = duk_get_length(thr, i);
25227 		len = (duk_uint32_t) tmp_len;
25228 		if (DUK_UNLIKELY(tmp_len != (duk_size_t) len)) {
25229 			goto fail_wrap;
25230 		}
25231 		if (DUK_UNLIKELY(idx + len < idx)) {
25232 			/* Result length must be at most 0xffffffffUL to be
25233 			 * a valid 32-bit array index.
25234 			 */
25235 			goto fail_wrap;
25236 		}
25237 		for (j = 0; j < len; j++) {
25238 			/* For a Proxy element, an explicit 'has' check is
25239 			 * needed to allow the Proxy to present gaps.
25240 			 */
25241 			if (need_has_check) {
25242 				if (duk_has_prop_index(thr, i, j)) {
25243 					duk_get_prop_index(thr, i, j);
25244 					duk_xdef_prop_index_wec(thr, -2, idx);
25245 				}
25246 			} else {
25247 				if (duk_get_prop_index(thr, i, j)) {
25248 					duk_xdef_prop_index_wec(thr, -2, idx);
25249 				} else {
25250 					duk_pop_undefined(thr);
25251 				}
25252 			}
25253 			idx++;
25254 			DUK_ASSERT(idx != 0U);  /* Wrap check above. */
25255 		}
25256 	}
25257 
25258 	/* ES5.1 has a specification "bug" in that nonexistent trailing
25259 	 * elements don't affect the result .length.  Test262 and other
25260 	 * engines disagree, and the specification bug was fixed in ES2015
25261 	 * (see NOTE 1 in https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.concat).
25262 	 */
25263 	duk_push_uarridx(thr, idx);
25264 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25265 
25266 	DUK_ASSERT_TOP(thr, n + 1);
25267 	return 1;
25268 
25269  fail_wrap:
25270 	DUK_ERROR_RANGE_INVALID_LENGTH(thr);
25271 	DUK_WO_NORETURN(return 0;);
25272 }
25273 
25274 /*
25275  *  join(), toLocaleString()
25276  *
25277  *  Note: checking valstack is necessary, but only in the per-element loop.
25278  *
25279  *  Note: the trivial approach of pushing all the elements on the value stack
25280  *  and then calling duk_join() fails when the array contains a large number
25281  *  of elements.  This problem can't be offloaded to duk_join() because the
25282  *  elements to join must be handled here and have special handling.  Current
25283  *  approach is to do intermediate joins with very large number of elements.
25284  *  There is no fancy handling; the prefix gets re-joined multiple times.
25285  */
25286 
duk_bi_array_prototype_join_shared(duk_hthread * thr)25287 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_join_shared(duk_hthread *thr) {
25288 	duk_uint32_t len, count;
25289 	duk_uint32_t idx;
25290 	duk_small_int_t to_locale_string = duk_get_current_magic(thr);
25291 	duk_idx_t valstack_required;
25292 
25293 	/* For join(), nargs is 1.  For toLocaleString(), nargs is 0 and
25294 	 * setting the top essentially pushes an undefined to the stack,
25295 	 * thus defaulting to a comma separator.
25296 	 */
25297 	duk_set_top(thr, 1);
25298 	if (duk_is_undefined(thr, 0)) {
25299 		duk_pop_undefined(thr);
25300 		duk_push_hstring_stridx(thr, DUK_STRIDX_COMMA);
25301 	} else {
25302 		duk_to_string(thr, 0);
25303 	}
25304 
25305 	len = duk__push_this_obj_len_u32(thr);
25306 
25307 	/* [ sep ToObject(this) len ] */
25308 
25309 	DUK_DDD(DUK_DDDPRINT("sep=%!T, this=%!T, len=%lu",
25310 	                     (duk_tval *) duk_get_tval(thr, 0),
25311 	                     (duk_tval *) duk_get_tval(thr, 1),
25312 	                     (unsigned long) len));
25313 
25314 	/* The extra (+4) is tight. */
25315 	valstack_required = (duk_idx_t) ((len >= DUK__ARRAY_MID_JOIN_LIMIT ?
25316 	                                  DUK__ARRAY_MID_JOIN_LIMIT : len) + 4);
25317 	duk_require_stack(thr, valstack_required);
25318 
25319 	duk_dup_0(thr);
25320 
25321 	/* [ sep ToObject(this) len sep ] */
25322 
25323 	count = 0;
25324 	idx = 0;
25325 	for (;;) {
25326 		DUK_DDD(DUK_DDDPRINT("join idx=%ld", (long) idx));
25327 		if (count >= DUK__ARRAY_MID_JOIN_LIMIT ||   /* intermediate join to avoid valstack overflow */
25328 		    idx >= len) { /* end of loop (careful with len==0) */
25329 			/* [ sep ToObject(this) len sep str0 ... str(count-1) ] */
25330 			DUK_DDD(DUK_DDDPRINT("mid/final join, count=%ld, idx=%ld, len=%ld",
25331 			                     (long) count, (long) idx, (long) len));
25332 			duk_join(thr, (duk_idx_t) count);  /* -> [ sep ToObject(this) len str ] */
25333 			duk_dup_0(thr);                    /* -> [ sep ToObject(this) len str sep ] */
25334 			duk_insert(thr, -2);               /* -> [ sep ToObject(this) len sep str ] */
25335 			count = 1;
25336 		}
25337 		if (idx >= len) {
25338 			/* if true, the stack already contains the final result */
25339 			break;
25340 		}
25341 
25342 		duk_get_prop_index(thr, 1, (duk_uarridx_t) idx);
25343 		if (duk_is_null_or_undefined(thr, -1)) {
25344 			duk_pop_nodecref_unsafe(thr);
25345 			duk_push_hstring_empty(thr);
25346 		} else {
25347 			if (to_locale_string) {
25348 				duk_to_object(thr, -1);
25349 				duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_LOCALE_STRING);
25350 				duk_insert(thr, -2);  /* -> [ ... toLocaleString ToObject(val) ] */
25351 				duk_call_method(thr, 0);
25352 			}
25353 			duk_to_string(thr, -1);
25354 		}
25355 
25356 		count++;
25357 		idx++;
25358 	}
25359 
25360 	/* [ sep ToObject(this) len sep result ] */
25361 
25362 	return 1;
25363 }
25364 
25365 /*
25366  *  pop(), push()
25367  */
25368 
25369 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_pop_fastpath(duk_hthread * thr,duk_harray * h_arr)25370 DUK_LOCAL duk_ret_t duk__array_pop_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25371 	duk_tval *tv_arraypart;
25372 	duk_tval *tv_val;
25373 	duk_uint32_t len;
25374 
25375 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25376 	len = h_arr->length;
25377 	if (len <= 0) {
25378 		/* nop, return undefined */
25379 		return 0;
25380 	}
25381 
25382 	len--;
25383 	h_arr->length = len;
25384 
25385 	/* Fast path doesn't check for an index property inherited from
25386 	 * Array.prototype.  This is quite often acceptable; if not,
25387 	 * disable fast path.
25388 	 */
25389 	DUK_ASSERT_VS_SPACE(thr);
25390 	tv_val = tv_arraypart + len;
25391 	if (DUK_TVAL_IS_UNUSED(tv_val)) {
25392 		/* No net refcount change.  Value stack already has
25393 		 * 'undefined' based on value stack init policy.
25394 		 */
25395 		DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
25396 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv_val));
25397 	} else {
25398 		/* No net refcount change. */
25399 		DUK_TVAL_SET_TVAL(thr->valstack_top, tv_val);
25400 		DUK_TVAL_SET_UNUSED(tv_val);
25401 	}
25402 	thr->valstack_top++;
25403 
25404 	/* XXX: there's no shrink check in the fast path now */
25405 
25406 	return 1;
25407 }
25408 #endif  /* DUK_USE_ARRAY_FASTPATH */
25409 
duk_bi_array_prototype_pop(duk_hthread * thr)25410 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_pop(duk_hthread *thr) {
25411 	duk_uint32_t len;
25412 	duk_uint32_t idx;
25413 #if defined(DUK_USE_ARRAY_FASTPATH)
25414 	duk_harray *h_arr;
25415 #endif
25416 
25417 	DUK_ASSERT_TOP(thr, 0);
25418 
25419 #if defined(DUK_USE_ARRAY_FASTPATH)
25420 	h_arr = duk__arraypart_fastpath_this(thr);
25421 	if (h_arr) {
25422 		return duk__array_pop_fastpath(thr, h_arr);
25423 	}
25424 #endif
25425 
25426 	/* XXX: Merge fastpath check into a related call (push this, coerce length, etc)? */
25427 
25428 	len = duk__push_this_obj_len_u32(thr);
25429 	if (len == 0) {
25430 		duk_push_int(thr, 0);
25431 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25432 		return 0;
25433 	}
25434 	idx = len - 1;
25435 
25436 	duk_get_prop_index(thr, 0, (duk_uarridx_t) idx);
25437 	duk_del_prop_index(thr, 0, (duk_uarridx_t) idx);
25438 	duk_push_u32(thr, idx);
25439 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
25440 	return 1;
25441 }
25442 
25443 #if defined(DUK_USE_ARRAY_FASTPATH)
duk__array_push_fastpath(duk_hthread * thr,duk_harray * h_arr)25444 DUK_LOCAL duk_ret_t duk__array_push_fastpath(duk_hthread *thr, duk_harray *h_arr) {
25445 	duk_tval *tv_arraypart;
25446 	duk_tval *tv_src;
25447 	duk_tval *tv_dst;
25448 	duk_uint32_t len;
25449 	duk_idx_t i, n;
25450 
25451 	len = h_arr->length;
25452 	tv_arraypart = DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) h_arr);
25453 
25454 	n = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
25455 	DUK_ASSERT(n >= 0);
25456 	DUK_ASSERT((duk_uint32_t) n <= DUK_UINT32_MAX);
25457 	if (DUK_UNLIKELY(len + (duk_uint32_t) n < len)) {
25458 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25459 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);  /* != 0 return value returned as is by caller */
25460 	}
25461 	if (len + (duk_uint32_t) n > DUK_HOBJECT_GET_ASIZE((duk_hobject *) h_arr)) {
25462 		/* Array part would need to be extended.  Rely on slow path
25463 		 * for now.
25464 		 *
25465 		 * XXX: Rework hobject code a bit and add extend support.
25466 		 */
25467 		return 0;
25468 	}
25469 
25470 	tv_src = thr->valstack_bottom;
25471 	tv_dst = tv_arraypart + len;
25472 	for (i = 0; i < n; i++) {
25473 		/* No net refcount change; reset value stack values to
25474 		 * undefined to satisfy value stack init policy.
25475 		 */
25476 		DUK_TVAL_SET_TVAL(tv_dst, tv_src);
25477 		DUK_TVAL_SET_UNDEFINED(tv_src);
25478 		tv_src++;
25479 		tv_dst++;
25480 	}
25481 	thr->valstack_top = thr->valstack_bottom;
25482 	len += (duk_uint32_t) n;
25483 	h_arr->length = len;
25484 
25485 	DUK_ASSERT((duk_uint_t) len == len);
25486 	duk_push_uint(thr, (duk_uint_t) len);
25487 	return 1;
25488 }
25489 #endif  /* DUK_USE_ARRAY_FASTPATH */
25490 
duk_bi_array_prototype_push(duk_hthread * thr)25491 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_push(duk_hthread *thr) {
25492 	/* Note: 'this' is not necessarily an Array object.  The push()
25493 	 * algorithm is supposed to work for other kinds of objects too,
25494 	 * so the algorithm has e.g. an explicit update for the 'length'
25495 	 * property which is normally "magical" in arrays.
25496 	 */
25497 
25498 	duk_uint32_t len;
25499 	duk_idx_t i, n;
25500 #if defined(DUK_USE_ARRAY_FASTPATH)
25501 	duk_harray *h_arr;
25502 #endif
25503 
25504 #if defined(DUK_USE_ARRAY_FASTPATH)
25505 	h_arr = duk__arraypart_fastpath_this(thr);
25506 	if (h_arr) {
25507 		duk_ret_t rc;
25508 		rc = duk__array_push_fastpath(thr, h_arr);
25509 		if (rc != 0) {
25510 			return rc;
25511 		}
25512 		DUK_DD(DUK_DDPRINT("array push() fast path exited, resize case"));
25513 	}
25514 #endif
25515 
25516 	n = duk_get_top(thr);
25517 	len = duk__push_this_obj_len_u32(thr);
25518 
25519 	/* [ arg1 ... argN obj length ] */
25520 
25521 	/* Technically Array.prototype.push() can create an Array with length
25522 	 * longer than 2^32-1, i.e. outside the 32-bit range.  The final length
25523 	 * is *not* wrapped to 32 bits in the specification.
25524 	 *
25525 	 * This implementation tracks length with a uint32 because it's much
25526 	 * more practical.
25527 	 *
25528 	 * See: test-bi-array-push-maxlen.js.
25529 	 */
25530 
25531 	if (len + (duk_uint32_t) n < len) {
25532 		DUK_D(DUK_DPRINT("Array.prototype.push() would go beyond 32-bit length, throw"));
25533 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25534 	}
25535 
25536 	for (i = 0; i < n; i++) {
25537 		duk_dup(thr, i);
25538 		duk_put_prop_index(thr, -3, (duk_uarridx_t) (len + (duk_uint32_t) i));
25539 	}
25540 	len += (duk_uint32_t) n;
25541 
25542 	duk_push_u32(thr, len);
25543 	duk_dup_top(thr);
25544 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
25545 
25546 	/* [ arg1 ... argN obj length new_length ] */
25547 	return 1;
25548 }
25549 
25550 /*
25551  *  sort()
25552  *
25553  *  Currently qsort with random pivot.  This is now really, really slow,
25554  *  because there is no fast path for array parts.
25555  *
25556  *  Signed indices are used because qsort() leaves and degenerate cases
25557  *  may use a negative offset.
25558  */
25559 
duk__array_sort_compare(duk_hthread * thr,duk_int_t idx1,duk_int_t idx2)25560 DUK_LOCAL duk_small_int_t duk__array_sort_compare(duk_hthread *thr, duk_int_t idx1, duk_int_t idx2) {
25561 	duk_bool_t have1, have2;
25562 	duk_bool_t undef1, undef2;
25563 	duk_small_int_t ret;
25564 	duk_idx_t idx_obj = 1;  /* fixed offsets in valstack */
25565 	duk_idx_t idx_fn = 0;
25566 	duk_hstring *h1, *h2;
25567 
25568 	/* Fast exit if indices are identical.  This is valid for a non-existent property,
25569 	 * for an undefined value, and almost always for ToString() coerced comparison of
25570 	 * arbitrary values (corner cases where this is not the case include e.g. a an
25571 	 * object with varying ToString() coercion).
25572 	 *
25573 	 * The specification does not prohibit "caching" of values read from the array, so
25574 	 * assuming equality for comparing an index with itself falls into the category of
25575 	 * "caching".
25576 	 *
25577 	 * Also, compareFn may be inconsistent, so skipping a call to compareFn here may
25578 	 * have an effect on the final result.  The specification does not require any
25579 	 * specific behavior for inconsistent compare functions, so again, this fast path
25580 	 * is OK.
25581 	 */
25582 
25583 	if (idx1 == idx2) {
25584 		DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld -> indices identical, quick exit",
25585 		                     (long) idx1, (long) idx2));
25586 		return 0;
25587 	}
25588 
25589 	have1 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx1);
25590 	have2 = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) idx2);
25591 
25592 	DUK_DDD(DUK_DDDPRINT("duk__array_sort_compare: idx1=%ld, idx2=%ld, have1=%ld, have2=%ld, val1=%!T, val2=%!T",
25593 	                     (long) idx1, (long) idx2, (long) have1, (long) have2,
25594 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
25595 
25596 	if (have1) {
25597 		if (have2) {
25598 			;
25599 		} else {
25600 			ret = -1;
25601 			goto pop_ret;
25602 		}
25603 	} else {
25604 		if (have2) {
25605 			ret = 1;
25606 			goto pop_ret;
25607 		} else {
25608 			ret = 0;
25609 			goto pop_ret;
25610 		}
25611 	}
25612 
25613 	undef1 = duk_is_undefined(thr, -2);
25614 	undef2 = duk_is_undefined(thr, -1);
25615 	if (undef1) {
25616 		if (undef2) {
25617 			ret = 0;
25618 			goto pop_ret;
25619 		} else {
25620 			ret = 1;
25621 			goto pop_ret;
25622 		}
25623 	} else {
25624 		if (undef2) {
25625 			ret = -1;
25626 			goto pop_ret;
25627 		} else {
25628 			;
25629 		}
25630 	}
25631 
25632 	if (!duk_is_undefined(thr, idx_fn)) {
25633 		duk_double_t d;
25634 
25635 		/* No need to check callable; duk_call() will do that. */
25636 		duk_dup(thr, idx_fn);    /* -> [ ... x y fn ] */
25637 		duk_insert(thr, -3);     /* -> [ ... fn x y ] */
25638 		duk_call(thr, 2);        /* -> [ ... res ] */
25639 
25640 		/* ES5 is a bit vague about what to do if the return value is
25641 		 * not a number.  ES2015 provides a concrete description:
25642 		 * http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare.
25643 		 */
25644 
25645 		d = duk_to_number_m1(thr);
25646 		if (d < 0.0) {
25647 			ret = -1;
25648 		} else if (d > 0.0) {
25649 			ret = 1;
25650 		} else {
25651 			/* Because NaN compares to false, NaN is handled here
25652 			 * without an explicit check above.
25653 			 */
25654 			ret = 0;
25655 		}
25656 
25657 		duk_pop_nodecref_unsafe(thr);
25658 		DUK_DDD(DUK_DDDPRINT("-> result %ld (from comparefn, after coercion)", (long) ret));
25659 		return ret;
25660 	}
25661 
25662 	/* string compare is the default (a bit oddly) */
25663 
25664 	/* XXX: any special handling for plain array; causes repeated coercion now? */
25665 	h1 = duk_to_hstring(thr, -2);
25666 	h2 = duk_to_hstring_m1(thr);
25667 	DUK_ASSERT(h1 != NULL);
25668 	DUK_ASSERT(h2 != NULL);
25669 
25670 	ret = duk_js_string_compare(h1, h2);  /* retval is directly usable */
25671 	goto pop_ret;
25672 
25673  pop_ret:
25674 	duk_pop_2_unsafe(thr);
25675 	DUK_DDD(DUK_DDDPRINT("-> result %ld", (long) ret));
25676 	return ret;
25677 }
25678 
duk__array_sort_swap(duk_hthread * thr,duk_int_t l,duk_int_t r)25679 DUK_LOCAL void duk__array_sort_swap(duk_hthread *thr, duk_int_t l, duk_int_t r) {
25680 	duk_bool_t have_l, have_r;
25681 	duk_idx_t idx_obj = 1;  /* fixed offset in valstack */
25682 
25683 	if (l == r) {
25684 		return;
25685 	}
25686 
25687 	/* swap elements; deal with non-existent elements correctly */
25688 	have_l = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25689 	have_r = duk_get_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25690 
25691 	if (have_r) {
25692 		/* right exists, [[Put]] regardless whether or not left exists */
25693 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25694 	} else {
25695 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) l);
25696 		duk_pop_undefined(thr);
25697 	}
25698 
25699 	if (have_l) {
25700 		duk_put_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25701 	} else {
25702 		duk_del_prop_index(thr, idx_obj, (duk_uarridx_t) r);
25703 		duk_pop_undefined(thr);
25704 	}
25705 }
25706 
25707 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25708 /* 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)25709 DUK_LOCAL void duk__debuglog_qsort_state(duk_hthread *thr, duk_int_t lo, duk_int_t hi, duk_int_t pivot) {
25710 	char buf[4096];
25711 	char *ptr = buf;
25712 	duk_int_t i, n;
25713 	n = (duk_int_t) duk_get_length(thr, 1);
25714 	if (n > 4000) {
25715 		n = 4000;
25716 	}
25717 	*ptr++ = '[';
25718 	for (i = 0; i < n; i++) {
25719 		if (i == pivot) {
25720 			*ptr++ = '|';
25721 		} else if (i == lo) {
25722 			*ptr++ = '<';
25723 		} else if (i == hi) {
25724 			*ptr++ = '>';
25725 		} else if (i >= lo && i <= hi) {
25726 			*ptr++ = '-';
25727 		} else {
25728 			*ptr++ = ' ';
25729 		}
25730 	}
25731 	*ptr++ = ']';
25732 	*ptr++ = '\0';
25733 
25734 	DUK_DDD(DUK_DDDPRINT("%s   (lo=%ld, hi=%ld, pivot=%ld)",
25735 	                     (const char *) buf, (long) lo, (long) hi, (long) pivot));
25736 }
25737 #endif
25738 
duk__array_qsort(duk_hthread * thr,duk_int_t lo,duk_int_t hi)25739 DUK_LOCAL void duk__array_qsort(duk_hthread *thr, duk_int_t lo, duk_int_t hi) {
25740 	duk_int_t p, l, r;
25741 
25742 	/* The lo/hi indices may be crossed and hi < 0 is possible at entry. */
25743 
25744 	DUK_DDD(DUK_DDDPRINT("duk__array_qsort: lo=%ld, hi=%ld, obj=%!T",
25745 	                     (long) lo, (long) hi, (duk_tval *) duk_get_tval(thr, 1)));
25746 
25747 	DUK_ASSERT_TOP(thr, 3);
25748 
25749 	/* In some cases it may be that lo > hi, or hi < 0; these
25750 	 * degenerate cases happen e.g. for empty arrays, and in
25751 	 * recursion leaves.
25752 	 */
25753 
25754 	/* trivial cases */
25755 	if (hi - lo < 1) {
25756 		DUK_DDD(DUK_DDDPRINT("degenerate case, return immediately"));
25757 		return;
25758 	}
25759 	DUK_ASSERT(hi > lo);
25760 	DUK_ASSERT(hi - lo + 1 >= 2);
25761 
25762 	/* randomized pivot selection */
25763 	p = lo + (duk_int_t) (DUK_UTIL_GET_RANDOM_DOUBLE(thr) * (duk_double_t) (hi - lo + 1));
25764 	DUK_ASSERT(p >= lo && p <= hi);
25765 	DUK_DDD(DUK_DDDPRINT("lo=%ld, hi=%ld, chose pivot p=%ld", (long) lo, (long) hi, (long) p));
25766 
25767 	/* move pivot out of the way */
25768 	duk__array_sort_swap(thr, p, lo);
25769 	p = lo;
25770 	DUK_DDD(DUK_DDDPRINT("pivot moved out of the way: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25771 
25772 	l = lo + 1;
25773 	r = hi;
25774 	for (;;) {
25775 		/* find elements to swap */
25776 		for (;;) {
25777 			DUK_DDD(DUK_DDDPRINT("left scan: l=%ld, r=%ld, p=%ld",
25778 			                     (long) l, (long) r, (long) p));
25779 			if (l >= hi) {
25780 				break;
25781 			}
25782 			if (duk__array_sort_compare(thr, l, p) >= 0) {  /* !(l < p) */
25783 				break;
25784 			}
25785 			l++;
25786 		}
25787 		for (;;) {
25788 			DUK_DDD(DUK_DDDPRINT("right scan: l=%ld, r=%ld, p=%ld",
25789 			                     (long) l, (long) r, (long) p));
25790 			if (r <= lo) {
25791 				break;
25792 			}
25793 			if (duk__array_sort_compare(thr, p, r) >= 0) {  /* !(p < r) */
25794 				break;
25795 			}
25796 			r--;
25797 		}
25798 		if (l >= r) {
25799 			goto done;
25800 		}
25801 		DUK_ASSERT(l < r);
25802 
25803 		DUK_DDD(DUK_DDDPRINT("swap %ld and %ld", (long) l, (long) r));
25804 
25805 		duk__array_sort_swap(thr, l, r);
25806 
25807 		DUK_DDD(DUK_DDDPRINT("after swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25808 		l++;
25809 		r--;
25810 	}
25811  done:
25812 	/* Note that 'l' and 'r' may cross, i.e. r < l */
25813 	DUK_ASSERT(l >= lo && l <= hi);
25814 	DUK_ASSERT(r >= lo && r <= hi);
25815 
25816 	/* XXX: there's no explicit recursion bound here now.  For the average
25817 	 * qsort recursion depth O(log n) that's not really necessary: e.g. for
25818 	 * 2**32 recursion depth would be about 32 which is OK.  However, qsort
25819 	 * worst case recursion depth is O(n) which may be a problem.
25820 	 */
25821 
25822 	/* move pivot to its final place */
25823 	DUK_DDD(DUK_DDDPRINT("before final pivot swap: %!T", (duk_tval *) duk_get_tval(thr, 1)));
25824 	duk__array_sort_swap(thr, lo, r);
25825 
25826 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
25827 	duk__debuglog_qsort_state(thr, lo, hi, r);
25828 #endif
25829 
25830 	DUK_DDD(DUK_DDDPRINT("recurse: pivot=%ld, obj=%!T", (long) r, (duk_tval *) duk_get_tval(thr, 1)));
25831 	duk__array_qsort(thr, lo, r - 1);
25832 	duk__array_qsort(thr, r + 1, hi);
25833 }
25834 
duk_bi_array_prototype_sort(duk_hthread * thr)25835 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_sort(duk_hthread *thr) {
25836 	duk_uint32_t len;
25837 
25838 	/* XXX: len >= 0x80000000 won't work below because a signed type
25839 	 * is needed by qsort.
25840 	 */
25841 	len = duk__push_this_obj_len_u32_limited(thr);
25842 
25843 	/* stack[0] = compareFn
25844 	 * stack[1] = ToObject(this)
25845 	 * stack[2] = ToUint32(length)
25846 	 */
25847 
25848 	if (len > 0) {
25849 		/* avoid degenerate cases, so that (len - 1) won't underflow */
25850 		duk__array_qsort(thr, (duk_int_t) 0, (duk_int_t) (len - 1));
25851 	}
25852 
25853 	DUK_ASSERT_TOP(thr, 3);
25854 	duk_pop_nodecref_unsafe(thr);
25855 	return 1;  /* return ToObject(this) */
25856 }
25857 
25858 /*
25859  *  splice()
25860  */
25861 
25862 /* XXX: this compiles to over 500 bytes now, even without special handling
25863  * for an array part.  Uses signed ints so does not handle full array range correctly.
25864  */
25865 
25866 /* XXX: can shift() / unshift() use the same helper?
25867  *   shift() is (close to?) <--> splice(0, 1)
25868  *   unshift is (close to?) <--> splice(0, 0, [items])?
25869  */
25870 
duk_bi_array_prototype_splice(duk_hthread * thr)25871 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_splice(duk_hthread *thr) {
25872 	duk_idx_t nargs;
25873 	duk_uint32_t len_u32;
25874 	duk_int_t len;
25875 	duk_bool_t have_delcount;
25876 	duk_int_t item_count;
25877 	duk_int_t act_start;
25878 	duk_int_t del_count;
25879 	duk_int_t i, n;
25880 
25881 	DUK_UNREF(have_delcount);
25882 
25883 	nargs = duk_get_top(thr);
25884 	if (nargs < 2) {
25885 		duk_set_top(thr, 2);
25886 		nargs = 2;
25887 		have_delcount = 0;
25888 	} else {
25889 		have_delcount = 1;
25890 	}
25891 
25892 	/* XXX: len >= 0x80000000 won't work below because we need to be
25893 	 * able to represent -len.
25894 	 */
25895 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
25896 	len = (duk_int_t) len_u32;
25897 	DUK_ASSERT(len >= 0);
25898 
25899 	act_start = duk_to_int_clamped(thr, 0, -len, len);
25900 	if (act_start < 0) {
25901 		act_start = len + act_start;
25902 	}
25903 	DUK_ASSERT(act_start >= 0 && act_start <= len);
25904 
25905 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
25906 	if (have_delcount) {
25907 #endif
25908 		del_count = duk_to_int_clamped(thr, 1, 0, len - act_start);
25909 #if defined(DUK_USE_NONSTD_ARRAY_SPLICE_DELCOUNT)
25910 	} else {
25911 		/* E5.1 standard behavior when deleteCount is not given would be
25912 		 * to treat it just like if 'undefined' was given, which coerces
25913 		 * ultimately to 0.  Real world behavior is to splice to the end
25914 		 * of array, see test-bi-array-proto-splice-no-delcount.js.
25915 		 */
25916 		del_count = len - act_start;
25917 	}
25918 #endif
25919 
25920 	DUK_ASSERT(nargs >= 2);
25921 	item_count = (duk_int_t) (nargs - 2);
25922 
25923 	DUK_ASSERT(del_count >= 0 && del_count <= len - act_start);
25924 	DUK_ASSERT(del_count + act_start <= len);
25925 
25926 	/* For now, restrict result array into 32-bit length range. */
25927 	if (((duk_double_t) len) - ((duk_double_t) del_count) + ((duk_double_t) item_count) > (duk_double_t) DUK_UINT32_MAX) {
25928 		DUK_D(DUK_DPRINT("Array.prototype.splice() would go beyond 32-bit length, throw"));
25929 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
25930 	}
25931 
25932 	duk_push_array(thr);
25933 
25934 	/* stack[0] = start
25935 	 * stack[1] = deleteCount
25936 	 * stack[2...nargs-1] = items
25937 	 * stack[nargs] = ToObject(this)               -3
25938 	 * stack[nargs+1] = ToUint32(length)           -2
25939 	 * stack[nargs+2] = result array               -1
25940 	 */
25941 
25942 	DUK_ASSERT_TOP(thr, nargs + 3);
25943 
25944 	/* Step 9: copy elements-to-be-deleted into the result array */
25945 
25946 	for (i = 0; i < del_count; i++) {
25947 		if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (act_start + i))) {
25948 			duk_xdef_prop_index_wec(thr, -2, (duk_uarridx_t) i);  /* throw flag irrelevant (false in std alg) */
25949 		} else {
25950 			duk_pop_undefined(thr);
25951 		}
25952 	}
25953 	duk_push_u32(thr, (duk_uint32_t) del_count);
25954 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
25955 
25956 	/* Steps 12 and 13: reorganize elements to make room for itemCount elements */
25957 
25958 	if (item_count < del_count) {
25959 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 1
25960 		 * -> [ A B F G H ]          (conceptual intermediate step)
25961 		 * -> [ A B . F G H ]        (placeholder marked)
25962 		 *    [ A B C F G H ]        (actual result at this point, C will be replaced)
25963 		 */
25964 
25965 		DUK_ASSERT_TOP(thr, nargs + 3);
25966 
25967 		n = len - del_count;
25968 		for (i = act_start; i < n; i++) {
25969 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
25970 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
25971 			} else {
25972 				duk_pop_undefined(thr);
25973 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
25974 			}
25975 		}
25976 
25977 		DUK_ASSERT_TOP(thr, nargs + 3);
25978 
25979 		/* loop iterator init and limit changed from standard algorithm */
25980 		n = len - del_count + item_count;
25981 		for (i = len - 1; i >= n; i--) {
25982 			duk_del_prop_index(thr, -3, (duk_uarridx_t) i);
25983 		}
25984 
25985 		DUK_ASSERT_TOP(thr, nargs + 3);
25986 	} else if (item_count > del_count) {
25987 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 4
25988 		 * -> [ A B F G H ]          (conceptual intermediate step)
25989 		 * -> [ A B . . . . F G H ]  (placeholder marked)
25990 		 *    [ A B C D E F F G H ]  (actual result at this point)
25991 		 */
25992 
25993 		DUK_ASSERT_TOP(thr, nargs + 3);
25994 
25995 		/* loop iterator init and limit changed from standard algorithm */
25996 		for (i = len - del_count - 1; i >= act_start; i--) {
25997 			if (duk_get_prop_index(thr, -3, (duk_uarridx_t) (i + del_count))) {
25998 				duk_put_prop_index(thr, -4, (duk_uarridx_t) (i + item_count));
25999 			} else {
26000 				duk_pop_undefined(thr);
26001 				duk_del_prop_index(thr, -3, (duk_uarridx_t) (i + item_count));
26002 			}
26003 		}
26004 
26005 		DUK_ASSERT_TOP(thr, nargs + 3);
26006 	} else {
26007 		/*    [ A B C D E F G H ]    rel_index = 2, del_count 3, item count 3
26008 		 * -> [ A B F G H ]          (conceptual intermediate step)
26009 		 * -> [ A B . . . F G H ]    (placeholder marked)
26010 		 *    [ A B C D E F G H ]    (actual result at this point)
26011 		 */
26012 	}
26013 	DUK_ASSERT_TOP(thr, nargs + 3);
26014 
26015 	/* Step 15: insert itemCount elements into the hole made above */
26016 
26017 	for (i = 0; i < item_count; i++) {
26018 		duk_dup(thr, i + 2);  /* args start at index 2 */
26019 		duk_put_prop_index(thr, -4, (duk_uarridx_t) (act_start + i));
26020 	}
26021 
26022 	/* Step 16: update length; note that the final length may be above 32 bit range
26023 	 * (but we checked above that this isn't the case here)
26024 	 */
26025 
26026 	duk_push_u32(thr, (duk_uint32_t) (len - del_count + item_count));
26027 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26028 
26029 	/* result array is already at the top of stack */
26030 	DUK_ASSERT_TOP(thr, nargs + 3);
26031 	return 1;
26032 }
26033 
26034 /*
26035  *  reverse()
26036  */
26037 
duk_bi_array_prototype_reverse(duk_hthread * thr)26038 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reverse(duk_hthread *thr) {
26039 	duk_uint32_t len;
26040 	duk_uint32_t middle;
26041 	duk_uint32_t lower, upper;
26042 	duk_bool_t have_lower, have_upper;
26043 
26044 	len = duk__push_this_obj_len_u32(thr);
26045 	middle = len / 2;
26046 
26047 	/* If len <= 1, middle will be 0 and for-loop bails out
26048 	 * immediately (0 < 0 -> false).
26049 	 */
26050 
26051 	for (lower = 0; lower < middle; lower++) {
26052 		DUK_ASSERT(len >= 2);
26053 		DUK_ASSERT_TOP(thr, 2);
26054 
26055 		DUK_ASSERT(len >= lower + 1);
26056 		upper = len - lower - 1;
26057 
26058 		have_lower = duk_get_prop_index(thr, -2, (duk_uarridx_t) lower);
26059 		have_upper = duk_get_prop_index(thr, -3, (duk_uarridx_t) upper);
26060 
26061 		/* [ ToObject(this) ToUint32(length) lowerValue upperValue ] */
26062 
26063 		if (have_upper) {
26064 			duk_put_prop_index(thr, -4, (duk_uarridx_t) lower);
26065 		} else {
26066 			duk_del_prop_index(thr, -4, (duk_uarridx_t) lower);
26067 			duk_pop_undefined(thr);
26068 		}
26069 
26070 		if (have_lower) {
26071 			duk_put_prop_index(thr, -3, (duk_uarridx_t) upper);
26072 		} else {
26073 			duk_del_prop_index(thr, -3, (duk_uarridx_t) upper);
26074 			duk_pop_undefined(thr);
26075 		}
26076 
26077 		DUK_ASSERT_TOP(thr, 2);
26078 	}
26079 
26080 	DUK_ASSERT_TOP(thr, 2);
26081 	duk_pop_unsafe(thr);  /* -> [ ToObject(this) ] */
26082 	return 1;
26083 }
26084 
26085 /*
26086  *  slice()
26087  */
26088 
duk_bi_array_prototype_slice(duk_hthread * thr)26089 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_slice(duk_hthread *thr) {
26090 	duk_uint32_t len_u32;
26091 	duk_int_t len;
26092 	duk_int_t start, end;
26093 	duk_int_t i;
26094 	duk_uarridx_t idx;
26095 	duk_uint32_t res_length = 0;
26096 
26097 	/* XXX: len >= 0x80000000 won't work below because we need to be
26098 	 * able to represent -len.
26099 	 */
26100 	len_u32 = duk__push_this_obj_len_u32_limited(thr);
26101 	len = (duk_int_t) len_u32;
26102 	DUK_ASSERT(len >= 0);
26103 
26104 	duk_push_array(thr);
26105 
26106 	/* stack[0] = start
26107 	 * stack[1] = end
26108 	 * stack[2] = ToObject(this)
26109 	 * stack[3] = ToUint32(length)
26110 	 * stack[4] = result array
26111 	 */
26112 
26113 	start = duk_to_int_clamped(thr, 0, -len, len);
26114 	if (start < 0) {
26115 		start = len + start;
26116 	}
26117 	/* XXX: could duk_is_undefined() provide defaulting undefined to 'len'
26118 	 * (the upper limit)?
26119 	 */
26120 	if (duk_is_undefined(thr, 1)) {
26121 		end = len;
26122 	} else {
26123 		end = duk_to_int_clamped(thr, 1, -len, len);
26124 		if (end < 0) {
26125 			end = len + end;
26126 		}
26127 	}
26128 	DUK_ASSERT(start >= 0 && start <= len);
26129 	DUK_ASSERT(end >= 0 && end <= len);
26130 
26131 	idx = 0;
26132 	for (i = start; i < end; i++) {
26133 		DUK_ASSERT_TOP(thr, 5);
26134 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26135 			duk_xdef_prop_index_wec(thr, 4, idx);
26136 			res_length = idx + 1;
26137 		} else {
26138 			duk_pop_undefined(thr);
26139 		}
26140 		idx++;
26141 		DUK_ASSERT_TOP(thr, 5);
26142 	}
26143 
26144 	duk_push_u32(thr, res_length);
26145 	duk_xdef_prop_stridx_short(thr, 4, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26146 
26147 	DUK_ASSERT_TOP(thr, 5);
26148 	return 1;
26149 }
26150 
26151 /*
26152  *  shift()
26153  */
26154 
duk_bi_array_prototype_shift(duk_hthread * thr)26155 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_shift(duk_hthread *thr) {
26156 	duk_uint32_t len;
26157 	duk_uint32_t i;
26158 
26159 	len = duk__push_this_obj_len_u32(thr);
26160 	if (len == 0) {
26161 		duk_push_int(thr, 0);
26162 		duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26163 		return 0;
26164 	}
26165 
26166 	duk_get_prop_index(thr, 0, 0);
26167 
26168 	/* stack[0] = object (this)
26169 	 * stack[1] = ToUint32(length)
26170 	 * stack[2] = elem at index 0 (retval)
26171 	 */
26172 
26173 	for (i = 1; i < len; i++) {
26174 		DUK_ASSERT_TOP(thr, 3);
26175 		if (duk_get_prop_index(thr, 0, (duk_uarridx_t) i)) {
26176 			/* fromPresent = true */
26177 			duk_put_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26178 		} else {
26179 			/* fromPresent = false */
26180 			duk_del_prop_index(thr, 0, (duk_uarridx_t) (i - 1));
26181 			duk_pop_undefined(thr);
26182 		}
26183 	}
26184 	duk_del_prop_index(thr, 0, (duk_uarridx_t) (len - 1));
26185 
26186 	duk_push_u32(thr, (duk_uint32_t) (len - 1));
26187 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
26188 
26189 	DUK_ASSERT_TOP(thr, 3);
26190 	return 1;
26191 }
26192 
26193 /*
26194  *  unshift()
26195  */
26196 
duk_bi_array_prototype_unshift(duk_hthread * thr)26197 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_unshift(duk_hthread *thr) {
26198 	duk_idx_t nargs;
26199 	duk_uint32_t len;
26200 	duk_uint32_t i;
26201 
26202 	nargs = duk_get_top(thr);
26203 	len = duk__push_this_obj_len_u32(thr);
26204 
26205 	/* stack[0...nargs-1] = unshift args (vararg)
26206 	 * stack[nargs] = ToObject(this)
26207 	 * stack[nargs+1] = ToUint32(length)
26208 	 */
26209 
26210 	DUK_ASSERT_TOP(thr, nargs + 2);
26211 
26212 	/* Note: unshift() may operate on indices above unsigned 32-bit range
26213 	 * and the final length may be >= 2**32.  However, we restrict the
26214 	 * final result to 32-bit range for practicality.
26215 	 */
26216 
26217 	if (len + (duk_uint32_t) nargs < len) {
26218 		DUK_D(DUK_DPRINT("Array.prototype.unshift() would go beyond 32-bit length, throw"));
26219 		DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
26220 	}
26221 
26222 	i = len;
26223 	while (i > 0) {
26224 		DUK_ASSERT_TOP(thr, nargs + 2);
26225 		i--;
26226 		/* k+argCount-1; note that may be above 32-bit range */
26227 
26228 		if (duk_get_prop_index(thr, -2, (duk_uarridx_t) i)) {
26229 			/* fromPresent = true */
26230 			/* [ ... ToObject(this) ToUint32(length) val ] */
26231 			duk_put_prop_index(thr, -3, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26232 		} else {
26233 			/* fromPresent = false */
26234 			/* [ ... ToObject(this) ToUint32(length) val ] */
26235 			duk_pop_undefined(thr);
26236 			duk_del_prop_index(thr, -2, (duk_uarridx_t) (i + (duk_uint32_t) nargs));  /* -> [ ... ToObject(this) ToUint32(length) ] */
26237 		}
26238 		DUK_ASSERT_TOP(thr, nargs + 2);
26239 	}
26240 
26241 	for (i = 0; i < (duk_uint32_t) nargs; i++) {
26242 		DUK_ASSERT_TOP(thr, nargs + 2);
26243 		duk_dup(thr, (duk_idx_t) i);  /* -> [ ... ToObject(this) ToUint32(length) arg[i] ] */
26244 		duk_put_prop_index(thr, -3, (duk_uarridx_t) i);
26245 		DUK_ASSERT_TOP(thr, nargs + 2);
26246 	}
26247 
26248 	DUK_ASSERT_TOP(thr, nargs + 2);
26249 	duk_push_u32(thr, len + (duk_uint32_t) nargs);
26250 	duk_dup_top(thr);  /* -> [ ... ToObject(this) ToUint32(length) final_len final_len ] */
26251 	duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_LENGTH);
26252 	return 1;
26253 }
26254 
26255 /*
26256  *  indexOf(), lastIndexOf()
26257  */
26258 
duk_bi_array_prototype_indexof_shared(duk_hthread * thr)26259 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_indexof_shared(duk_hthread *thr) {
26260 	duk_idx_t nargs;
26261 	duk_int_t i, len;
26262 	duk_int_t from_idx;
26263 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for indexOf, -1 for lastIndexOf */
26264 
26265 	/* lastIndexOf() needs to be a vararg function because we must distinguish
26266 	 * between an undefined fromIndex and a "not given" fromIndex; indexOf() is
26267 	 * made vararg for symmetry although it doesn't strictly need to be.
26268 	 */
26269 
26270 	nargs = duk_get_top(thr);
26271 	duk_set_top(thr, 2);
26272 
26273 	/* XXX: must be able to represent -len */
26274 	len = (duk_int_t) duk__push_this_obj_len_u32_limited(thr);
26275 	if (len == 0) {
26276 		goto not_found;
26277 	}
26278 
26279 	/* Index clamping is a bit tricky, we must ensure that we'll only iterate
26280 	 * through elements that exist and that the specific requirements from E5.1
26281 	 * Sections 15.4.4.14 and 15.4.4.15 are fulfilled; especially:
26282 	 *
26283 	 *   - indexOf: clamp to [-len,len], negative handling -> [0,len],
26284 	 *     if clamped result is len, for-loop bails out immediately
26285 	 *
26286 	 *   - lastIndexOf: clamp to [-len-1, len-1], negative handling -> [-1, len-1],
26287 	 *     if clamped result is -1, for-loop bails out immediately
26288 	 *
26289 	 * If fromIndex is not given, ToInteger(undefined) = 0, which is correct
26290 	 * for indexOf() but incorrect for lastIndexOf().  Hence special handling,
26291 	 * and why lastIndexOf() needs to be a vararg function.
26292 	 */
26293 
26294 	if (nargs >= 2) {
26295 		/* indexOf: clamp fromIndex to [-len, len]
26296 		 * (if fromIndex == len, for-loop terminates directly)
26297 		 *
26298 		 * lastIndexOf: clamp fromIndex to [-len - 1, len - 1]
26299 		 * (if clamped to -len-1 -> fromIndex becomes -1, terminates for-loop directly)
26300 		 */
26301 		from_idx = duk_to_int_clamped(thr,
26302 		                              1,
26303 		                              (idx_step > 0 ? -len : -len - 1),
26304 		                              (idx_step > 0 ? len : len - 1));
26305 		if (from_idx < 0) {
26306 			/* for lastIndexOf, result may be -1 (mark immediate termination) */
26307 			from_idx = len + from_idx;
26308 		}
26309 	} else {
26310 		/* for indexOf, ToInteger(undefined) would be 0, i.e. correct, but
26311 		 * handle both indexOf and lastIndexOf specially here.
26312 		 */
26313 		if (idx_step > 0) {
26314 			from_idx = 0;
26315 		} else {
26316 			from_idx = len - 1;
26317 		}
26318 	}
26319 
26320 	/* stack[0] = searchElement
26321 	 * stack[1] = fromIndex
26322 	 * stack[2] = object
26323 	 * stack[3] = length (not needed, but not popped above)
26324 	 */
26325 
26326 	for (i = from_idx; i >= 0 && i < len; i += idx_step) {
26327 		DUK_ASSERT_TOP(thr, 4);
26328 
26329 		if (duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26330 			DUK_ASSERT_TOP(thr, 5);
26331 			if (duk_strict_equals(thr, 0, 4)) {
26332 				duk_push_int(thr, i);
26333 				return 1;
26334 			}
26335 		}
26336 
26337 		duk_pop_unsafe(thr);
26338 	}
26339 
26340  not_found:
26341 	duk_push_int(thr, -1);
26342 	return 1;
26343 }
26344 
26345 /*
26346  *  every(), some(), forEach(), map(), filter()
26347  */
26348 
26349 #define DUK__ITER_EVERY    0
26350 #define DUK__ITER_SOME     1
26351 #define DUK__ITER_FOREACH  2
26352 #define DUK__ITER_MAP      3
26353 #define DUK__ITER_FILTER   4
26354 
26355 /* XXX: This helper is a bit awkward because the handling for the different iteration
26356  * callers is quite different.  This now compiles to a bit less than 500 bytes, so with
26357  * 5 callers the net result is about 100 bytes / caller.
26358  */
26359 
duk_bi_array_prototype_iter_shared(duk_hthread * thr)26360 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_iter_shared(duk_hthread *thr) {
26361 	duk_uint32_t len;
26362 	duk_uint32_t i;
26363 	duk_uarridx_t k;
26364 	duk_bool_t bval;
26365 	duk_small_int_t iter_type = duk_get_current_magic(thr);
26366 	duk_uint32_t res_length = 0;
26367 
26368 	/* each call this helper serves has nargs==2 */
26369 	DUK_ASSERT_TOP(thr, 2);
26370 
26371 	len = duk__push_this_obj_len_u32(thr);
26372 	duk_require_callable(thr, 0);
26373 	/* if thisArg not supplied, behave as if undefined was supplied */
26374 
26375 	if (iter_type == DUK__ITER_MAP || iter_type == DUK__ITER_FILTER) {
26376 		duk_push_array(thr);
26377 	} else {
26378 		duk_push_undefined(thr);
26379 	}
26380 
26381 	/* stack[0] = callback
26382 	 * stack[1] = thisArg
26383 	 * stack[2] = object
26384 	 * stack[3] = ToUint32(length)  (unused, but avoid unnecessary pop)
26385 	 * stack[4] = result array (or undefined)
26386 	 */
26387 
26388 	k = 0;  /* result index for filter() */
26389 	for (i = 0; i < len; i++) {
26390 		DUK_ASSERT_TOP(thr, 5);
26391 
26392 		if (!duk_get_prop_index(thr, 2, (duk_uarridx_t) i)) {
26393 			/* For 'map' trailing missing elements don't invoke the
26394 			 * callback but count towards the result length.
26395 			 */
26396 			if (iter_type == DUK__ITER_MAP) {
26397 				res_length = i + 1;
26398 			}
26399 			duk_pop_undefined(thr);
26400 			continue;
26401 		}
26402 
26403 		/* The original value needs to be preserved for filter(), hence
26404 		 * this funny order.  We can't re-get the value because of side
26405 		 * effects.
26406 		 */
26407 
26408 		duk_dup_0(thr);
26409 		duk_dup_1(thr);
26410 		duk_dup_m3(thr);
26411 		duk_push_u32(thr, i);
26412 		duk_dup_2(thr);  /* [ ... val callback thisArg val i obj ] */
26413 		duk_call_method(thr, 3); /* -> [ ... val retval ] */
26414 
26415 		switch (iter_type) {
26416 		case DUK__ITER_EVERY:
26417 			bval = duk_to_boolean(thr, -1);
26418 			if (!bval) {
26419 				/* stack top contains 'false' */
26420 				return 1;
26421 			}
26422 			break;
26423 		case DUK__ITER_SOME:
26424 			bval = duk_to_boolean(thr, -1);
26425 			if (bval) {
26426 				/* stack top contains 'true' */
26427 				return 1;
26428 			}
26429 			break;
26430 		case DUK__ITER_FOREACH:
26431 			/* nop */
26432 			break;
26433 		case DUK__ITER_MAP:
26434 			duk_dup_top(thr);
26435 			duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) i);  /* retval to result[i] */
26436 			res_length = i + 1;
26437 			break;
26438 		case DUK__ITER_FILTER:
26439 			bval = duk_to_boolean(thr, -1);
26440 			if (bval) {
26441 				duk_dup_m2(thr);  /* orig value */
26442 				duk_xdef_prop_index_wec(thr, 4, (duk_uarridx_t) k);
26443 				k++;
26444 				res_length = k;
26445 			}
26446 			break;
26447 		default:
26448 			DUK_UNREACHABLE();
26449 			break;
26450 		}
26451 		duk_pop_2_unsafe(thr);
26452 
26453 		DUK_ASSERT_TOP(thr, 5);
26454 	}
26455 
26456 	switch (iter_type) {
26457 	case DUK__ITER_EVERY:
26458 		duk_push_true(thr);
26459 		break;
26460 	case DUK__ITER_SOME:
26461 		duk_push_false(thr);
26462 		break;
26463 	case DUK__ITER_FOREACH:
26464 		duk_push_undefined(thr);
26465 		break;
26466 	case DUK__ITER_MAP:
26467 	case DUK__ITER_FILTER:
26468 		DUK_ASSERT_TOP(thr, 5);
26469 		DUK_ASSERT(duk_is_array(thr, -1));  /* topmost element is the result array already */
26470 		duk_push_u32(thr, res_length);
26471 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);
26472 		break;
26473 	default:
26474 		DUK_UNREACHABLE();
26475 		break;
26476 	}
26477 
26478 	return 1;
26479 }
26480 
26481 /*
26482  *  reduce(), reduceRight()
26483  */
26484 
duk_bi_array_prototype_reduce_shared(duk_hthread * thr)26485 DUK_INTERNAL duk_ret_t duk_bi_array_prototype_reduce_shared(duk_hthread *thr) {
26486 	duk_idx_t nargs;
26487 	duk_bool_t have_acc;
26488 	duk_uint32_t i, len;
26489 	duk_small_int_t idx_step = duk_get_current_magic(thr);  /* idx_step is +1 for reduce, -1 for reduceRight */
26490 
26491 	/* We're a varargs function because we need to detect whether
26492 	 * initialValue was given or not.
26493 	 */
26494 	nargs = duk_get_top(thr);
26495 	DUK_DDD(DUK_DDDPRINT("nargs=%ld", (long) nargs));
26496 
26497 	duk_set_top(thr, 2);
26498 	len = duk__push_this_obj_len_u32(thr);
26499 	duk_require_callable(thr, 0);
26500 
26501 	/* stack[0] = callback fn
26502 	 * stack[1] = initialValue
26503 	 * stack[2] = object (coerced this)
26504 	 * stack[3] = length (not needed, but not popped above)
26505 	 * stack[4] = accumulator
26506 	 */
26507 
26508 	have_acc = 0;
26509 	if (nargs >= 2) {
26510 		duk_dup_1(thr);
26511 		have_acc = 1;
26512 	}
26513 	DUK_DDD(DUK_DDDPRINT("have_acc=%ld, acc=%!T",
26514 	                     (long) have_acc, (duk_tval *) duk_get_tval(thr, 3)));
26515 
26516 	/* For len == 0, i is initialized to len - 1 which underflows.
26517 	 * The condition (i < len) will then exit the for-loop on the
26518 	 * first round which is correct.  Similarly, loop termination
26519 	 * happens by i underflowing.
26520 	 */
26521 
26522 	for (i = (idx_step >= 0 ? 0 : len - 1);
26523 	     i < len;  /* i >= 0 would always be true */
26524 	     i += (duk_uint32_t) idx_step) {
26525 		DUK_DDD(DUK_DDDPRINT("i=%ld, len=%ld, have_acc=%ld, top=%ld, acc=%!T",
26526 		                     (long) i, (long) len, (long) have_acc,
26527 		                     (long) duk_get_top(thr),
26528 		                     (duk_tval *) duk_get_tval(thr, 4)));
26529 
26530 		DUK_ASSERT((have_acc && duk_get_top(thr) == 5) ||
26531 		           (!have_acc && duk_get_top(thr) == 4));
26532 
26533 		if (!duk_has_prop_index(thr, 2, (duk_uarridx_t) i)) {
26534 			continue;
26535 		}
26536 
26537 		if (!have_acc) {
26538 			DUK_ASSERT_TOP(thr, 4);
26539 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26540 			have_acc = 1;
26541 			DUK_ASSERT_TOP(thr, 5);
26542 		} else {
26543 			DUK_ASSERT_TOP(thr, 5);
26544 			duk_dup_0(thr);
26545 			duk_dup(thr, 4);
26546 			duk_get_prop_index(thr, 2, (duk_uarridx_t) i);
26547 			duk_push_u32(thr, i);
26548 			duk_dup_2(thr);
26549 			DUK_DDD(DUK_DDDPRINT("calling reduce function: func=%!T, prev=%!T, curr=%!T, idx=%!T, obj=%!T",
26550 			                     (duk_tval *) duk_get_tval(thr, -5), (duk_tval *) duk_get_tval(thr, -4),
26551 			                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
26552 			                     (duk_tval *) duk_get_tval(thr, -1)));
26553 			duk_call(thr, 4);
26554 			DUK_DDD(DUK_DDDPRINT("-> result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
26555 			duk_replace(thr, 4);
26556 			DUK_ASSERT_TOP(thr, 5);
26557 		}
26558 	}
26559 
26560 	if (!have_acc) {
26561 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26562 	}
26563 
26564 	DUK_ASSERT_TOP(thr, 5);
26565 	return 1;
26566 }
26567 
26568 #endif  /* DUK_USE_ARRAY_BUILTIN */
26569 
26570 /* automatic undefs */
26571 #undef DUK__ARRAY_MID_JOIN_LIMIT
26572 #undef DUK__ITER_EVERY
26573 #undef DUK__ITER_FILTER
26574 #undef DUK__ITER_FOREACH
26575 #undef DUK__ITER_MAP
26576 #undef DUK__ITER_SOME
26577 #line 1 "duk_bi_boolean.c"
26578 /*
26579  *  Boolean built-ins
26580  */
26581 
26582 /* #include duk_internal.h -> already included */
26583 
26584 #if defined(DUK_USE_BOOLEAN_BUILTIN)
26585 
26586 /* Shared helper to provide toString() and valueOf().  Checks 'this', gets
26587  * the primitive value to stack top, and optionally coerces with ToString().
26588  */
duk_bi_boolean_prototype_tostring_shared(duk_hthread * thr)26589 DUK_INTERNAL duk_ret_t duk_bi_boolean_prototype_tostring_shared(duk_hthread *thr) {
26590 	duk_tval *tv;
26591 	duk_hobject *h;
26592 	duk_small_int_t coerce_tostring = duk_get_current_magic(thr);
26593 
26594 	/* XXX: there is room to use a shared helper here, many built-ins
26595 	 * check the 'this' type, and if it's an object, check its class,
26596 	 * then get its internal value, etc.
26597 	 */
26598 
26599 	duk_push_this(thr);
26600 	tv = duk_get_tval(thr, -1);
26601 	DUK_ASSERT(tv != NULL);
26602 
26603 	if (DUK_TVAL_IS_BOOLEAN(tv)) {
26604 		goto type_ok;
26605 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
26606 		h = DUK_TVAL_GET_OBJECT(tv);
26607 		DUK_ASSERT(h != NULL);
26608 
26609 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_BOOLEAN) {
26610 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
26611 			DUK_ASSERT(duk_is_boolean(thr, -1));
26612 			goto type_ok;
26613 		}
26614 	}
26615 
26616 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
26617 	/* never here */
26618 
26619  type_ok:
26620 	if (coerce_tostring) {
26621 		duk_to_string(thr, -1);
26622 	}
26623 	return 1;
26624 }
26625 
duk_bi_boolean_constructor(duk_hthread * thr)26626 DUK_INTERNAL duk_ret_t duk_bi_boolean_constructor(duk_hthread *thr) {
26627 	duk_hobject *h_this;
26628 
26629 	duk_to_boolean(thr, 0);
26630 
26631 	if (duk_is_constructor_call(thr)) {
26632 		/* XXX: helper; rely on Boolean.prototype as being non-writable, non-configurable */
26633 		duk_push_this(thr);
26634 		h_this = duk_known_hobject(thr, -1);
26635 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE]);
26636 
26637 		DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_BOOLEAN);
26638 
26639 		duk_dup_0(thr);  /* -> [ val obj val ] */
26640 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);  /* XXX: proper flags? */
26641 	}  /* unbalanced stack */
26642 
26643 	return 1;
26644 }
26645 
26646 #endif  /* DUK_USE_BOOLEAN_BUILTIN */
26647 #line 1 "duk_bi_buffer.c"
26648 /*
26649  *  ES2015 TypedArray and Node.js Buffer built-ins
26650  */
26651 
26652 /* #include duk_internal.h -> already included */
26653 
26654 /*
26655  *  Helpers for buffer handling, enabled with DUK_USE_BUFFEROBJECT_SUPPORT.
26656  */
26657 
26658 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
26659 /* Map class number (minus DUK_HOBJECT_CLASS_BUFOBJ_MIN) to a bidx for the
26660  * default internal prototype.
26661  */
26662 static const duk_uint8_t duk__buffer_proto_from_classnum[] = {
26663 	DUK_BIDX_ARRAYBUFFER_PROTOTYPE,
26664 	DUK_BIDX_DATAVIEW_PROTOTYPE,
26665 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26666 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26667 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26668 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26669 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26670 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26671 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26672 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26673 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26674 };
26675 
26676 /* Map DUK_HBUFOBJ_ELEM_xxx to duk_hobject class number.
26677  * Sync with duk_hbufobj.h and duk_hobject.h.
26678  */
26679 static const duk_uint8_t duk__buffer_class_from_elemtype[9] = {
26680 	DUK_HOBJECT_CLASS_UINT8ARRAY,
26681 	DUK_HOBJECT_CLASS_UINT8CLAMPEDARRAY,
26682 	DUK_HOBJECT_CLASS_INT8ARRAY,
26683 	DUK_HOBJECT_CLASS_UINT16ARRAY,
26684 	DUK_HOBJECT_CLASS_INT16ARRAY,
26685 	DUK_HOBJECT_CLASS_UINT32ARRAY,
26686 	DUK_HOBJECT_CLASS_INT32ARRAY,
26687 	DUK_HOBJECT_CLASS_FLOAT32ARRAY,
26688 	DUK_HOBJECT_CLASS_FLOAT64ARRAY
26689 };
26690 
26691 /* Map DUK_HBUFOBJ_ELEM_xxx to prototype object built-in index.
26692  * Sync with duk_hbufobj.h.
26693  */
26694 static const duk_uint8_t duk__buffer_proto_from_elemtype[9] = {
26695 	DUK_BIDX_UINT8ARRAY_PROTOTYPE,
26696 	DUK_BIDX_UINT8CLAMPEDARRAY_PROTOTYPE,
26697 	DUK_BIDX_INT8ARRAY_PROTOTYPE,
26698 	DUK_BIDX_UINT16ARRAY_PROTOTYPE,
26699 	DUK_BIDX_INT16ARRAY_PROTOTYPE,
26700 	DUK_BIDX_UINT32ARRAY_PROTOTYPE,
26701 	DUK_BIDX_INT32ARRAY_PROTOTYPE,
26702 	DUK_BIDX_FLOAT32ARRAY_PROTOTYPE,
26703 	DUK_BIDX_FLOAT64ARRAY_PROTOTYPE
26704 };
26705 
26706 /* Map DUK__FLD_xxx to byte size. */
26707 static const duk_uint8_t duk__buffer_nbytes_from_fldtype[6] = {
26708 	1,  /* DUK__FLD_8BIT */
26709 	2,  /* DUK__FLD_16BIT */
26710 	4,  /* DUK__FLD_32BIT */
26711 	4,  /* DUK__FLD_FLOAT */
26712 	8,  /* DUK__FLD_DOUBLE */
26713 	0   /* DUK__FLD_VARINT; not relevant here */
26714 };
26715 
26716 /* Bitfield for each DUK_HBUFOBJ_ELEM_xxx indicating which element types
26717  * are compatible with a blind byte copy for the TypedArray set() method (also
26718  * used for TypedArray constructor).  Array index is target buffer elem type,
26719  * bitfield indicates compatible source types.  The types must have same byte
26720  * size and they must be coercion compatible.
26721  */
26722 #if !defined(DUK_USE_PREFER_SIZE)
26723 static duk_uint16_t duk__buffer_elemtype_copy_compatible[9] = {
26724 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8 */
26725 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26726 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26727 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26728 
26729 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT8CLAMPED
26730 	 * Note: INT8 is -not- copy compatible, e.g. -1 would coerce to 0x00.
26731 	 */
26732 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26733 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED),
26734 
26735 	/* xxx -> DUK_HBUFOBJ_ELEM_INT8 */
26736 	(1U << DUK_HBUFOBJ_ELEM_UINT8) |
26737 		(1U << DUK_HBUFOBJ_ELEM_UINT8CLAMPED) |
26738 		(1U << DUK_HBUFOBJ_ELEM_INT8),
26739 
26740 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT16 */
26741 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26742 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26743 
26744 	/* xxx -> DUK_HBUFOBJ_ELEM_INT16 */
26745 	(1U << DUK_HBUFOBJ_ELEM_UINT16) |
26746 		(1U << DUK_HBUFOBJ_ELEM_INT16),
26747 
26748 	/* xxx -> DUK_HBUFOBJ_ELEM_UINT32 */
26749 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26750 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26751 
26752 	/* xxx -> DUK_HBUFOBJ_ELEM_INT32 */
26753 	(1U << DUK_HBUFOBJ_ELEM_UINT32) |
26754 		(1U << DUK_HBUFOBJ_ELEM_INT32),
26755 
26756 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT32 */
26757 	(1U << DUK_HBUFOBJ_ELEM_FLOAT32),
26758 
26759 	/* xxx -> DUK_HBUFOBJ_ELEM_FLOAT64 */
26760 	(1U << DUK_HBUFOBJ_ELEM_FLOAT64)
26761 };
26762 #endif  /* !DUK_USE_PREFER_SIZE */
26763 
duk__hbufobj_promote_this(duk_hthread * thr)26764 DUK_LOCAL duk_hbufobj *duk__hbufobj_promote_this(duk_hthread *thr) {
26765 	duk_tval *tv_dst;
26766 	duk_hbufobj *res;
26767 
26768 	duk_push_this(thr);
26769 	DUK_ASSERT(duk_is_buffer(thr, -1));
26770 	res = (duk_hbufobj *) duk_to_hobject(thr, -1);
26771 	DUK_ASSERT_HBUFOBJ_VALID(res);
26772 	DUK_DD(DUK_DDPRINT("promoted 'this' automatically to an ArrayBuffer: %!iT", duk_get_tval(thr, -1)));
26773 
26774 	tv_dst = duk_get_borrowed_this_tval(thr);
26775 	DUK_TVAL_SET_OBJECT_UPDREF(thr, tv_dst, (duk_hobject *) res);
26776 	duk_pop(thr);
26777 
26778 	return res;
26779 }
26780 
26781 #define DUK__BUFOBJ_FLAG_THROW    (1 << 0)
26782 #define DUK__BUFOBJ_FLAG_PROMOTE  (1 << 1)
26783 
26784 /* Shared helper.  When DUK__BUFOBJ_FLAG_PROMOTE is given, the return value is
26785  * always a duk_hbufobj *.  Without the flag the return value can also be a
26786  * plain buffer, and the caller must check for it using DUK_HEAPHDR_IS_BUFFER().
26787  */
duk__getrequire_bufobj_this(duk_hthread * thr,duk_small_uint_t flags)26788 DUK_LOCAL duk_heaphdr *duk__getrequire_bufobj_this(duk_hthread *thr, duk_small_uint_t flags) {
26789 	duk_tval *tv;
26790 	duk_hbufobj *h_this;
26791 
26792 	DUK_ASSERT(thr != NULL);
26793 
26794 	tv = duk_get_borrowed_this_tval(thr);
26795 	DUK_ASSERT(tv != NULL);
26796 
26797 	if (DUK_TVAL_IS_OBJECT(tv)) {
26798 		h_this = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
26799 		DUK_ASSERT(h_this != NULL);
26800 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_this)) {
26801 			DUK_ASSERT_HBUFOBJ_VALID(h_this);
26802 			return (duk_heaphdr *) h_this;
26803 		}
26804 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
26805 		if (flags & DUK__BUFOBJ_FLAG_PROMOTE) {
26806 			/* Promote a plain buffer to a Uint8Array.  This is very
26807 			 * inefficient but allows plain buffer to be used wherever an
26808 			 * Uint8Array is used with very small cost; hot path functions
26809 			 * like index read/write calls should provide direct buffer
26810 			 * support to avoid promotion.
26811 			 */
26812 			/* XXX: make this conditional to a flag if call sites need it? */
26813 			h_this = duk__hbufobj_promote_this(thr);
26814 			DUK_ASSERT(h_this != NULL);
26815 			DUK_ASSERT_HBUFOBJ_VALID(h_this);
26816 			return (duk_heaphdr *) h_this;
26817 		} else {
26818 			/* XXX: ugly, share return pointer for duk_hbuffer. */
26819 			return (duk_heaphdr *) DUK_TVAL_GET_BUFFER(tv);
26820 		}
26821 	}
26822 
26823 	if (flags & DUK__BUFOBJ_FLAG_THROW) {
26824 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
26825 		DUK_WO_NORETURN(return NULL;);
26826 	}
26827 	return NULL;
26828 }
26829 
26830 /* Check that 'this' is a duk_hbufobj and return a pointer to it. */
duk__get_bufobj_this(duk_hthread * thr)26831 DUK_LOCAL duk_hbufobj *duk__get_bufobj_this(duk_hthread *thr) {
26832 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_PROMOTE);
26833 }
26834 
26835 /* Check that 'this' is a duk_hbufobj and return a pointer to it
26836  * (NULL if not).
26837  */
duk__require_bufobj_this(duk_hthread * thr)26838 DUK_LOCAL duk_hbufobj *duk__require_bufobj_this(duk_hthread *thr) {
26839 	return (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW | DUK__BUFOBJ_FLAG_PROMOTE);
26840 }
26841 
26842 /* Check that value is a duk_hbufobj and return a pointer to it. */
duk__require_bufobj_value(duk_hthread * thr,duk_idx_t idx)26843 DUK_LOCAL duk_hbufobj *duk__require_bufobj_value(duk_hthread *thr, duk_idx_t idx) {
26844 	duk_tval *tv;
26845 	duk_hbufobj *h_obj;
26846 
26847 	/* Don't accept relative indices now. */
26848 	DUK_ASSERT(idx >= 0);
26849 
26850 	tv = duk_require_tval(thr, idx);
26851 	DUK_ASSERT(tv != NULL);
26852 	if (DUK_TVAL_IS_OBJECT(tv)) {
26853 		h_obj = (duk_hbufobj *) DUK_TVAL_GET_OBJECT(tv);
26854 		DUK_ASSERT(h_obj != NULL);
26855 		if (DUK_HOBJECT_IS_BUFOBJ((duk_hobject *) h_obj)) {
26856 			DUK_ASSERT_HBUFOBJ_VALID(h_obj);
26857 			return h_obj;
26858 		}
26859 	} else if (DUK_TVAL_IS_BUFFER(tv)) {
26860 		h_obj = (duk_hbufobj *) duk_to_hobject(thr, idx);
26861 		DUK_ASSERT(h_obj != NULL);
26862 		DUK_ASSERT_HBUFOBJ_VALID(h_obj);
26863 		return h_obj;
26864 	}
26865 
26866 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_BUFFER);
26867 	DUK_WO_NORETURN(return NULL;);
26868 }
26869 
duk__set_bufobj_buffer(duk_hthread * thr,duk_hbufobj * h_bufobj,duk_hbuffer * h_val)26870 DUK_LOCAL void duk__set_bufobj_buffer(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_hbuffer *h_val) {
26871 	DUK_ASSERT(thr != NULL);
26872 	DUK_ASSERT(h_bufobj != NULL);
26873 	DUK_ASSERT(h_bufobj->buf == NULL);  /* no need to decref */
26874 	DUK_ASSERT(h_val != NULL);
26875 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
26876 	DUK_UNREF(thr);
26877 
26878 	h_bufobj->buf = h_val;
26879 	DUK_HBUFFER_INCREF(thr, h_val);
26880 	h_bufobj->length = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_val);
26881 	DUK_ASSERT(h_bufobj->shift == 0);
26882 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
26883 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
26884 
26885 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
26886 }
26887 
26888 /* 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)26889 DUK_LOCAL void duk__resolve_offset_opt_length(duk_hthread *thr,
26890                                               duk_hbufobj *h_bufarg,
26891                                               duk_idx_t idx_offset,
26892                                               duk_idx_t idx_length,
26893                                               duk_uint_t *out_offset,
26894                                               duk_uint_t *out_length,
26895                                               duk_bool_t throw_flag) {
26896 	duk_int_t offset_signed;
26897 	duk_int_t length_signed;
26898 	duk_uint_t offset;
26899 	duk_uint_t length;
26900 
26901 	offset_signed = duk_to_int(thr, idx_offset);
26902 	if (offset_signed < 0) {
26903 		goto fail_range;
26904 	}
26905 	offset = (duk_uint_t) offset_signed;
26906 	if (offset > h_bufarg->length) {
26907 		goto fail_range;
26908 	}
26909 	DUK_ASSERT_DISABLE(offset >= 0);  /* unsigned */
26910 	DUK_ASSERT(offset <= h_bufarg->length);
26911 
26912 	if (duk_is_undefined(thr, idx_length)) {
26913 		DUK_ASSERT(h_bufarg->length >= offset);
26914 		length = h_bufarg->length - offset;  /* >= 0 */
26915 	} else {
26916 		length_signed = duk_to_int(thr, idx_length);
26917 		if (length_signed < 0) {
26918 			goto fail_range;
26919 		}
26920 		length = (duk_uint_t) length_signed;
26921 		DUK_ASSERT(h_bufarg->length >= offset);
26922 		if (length > h_bufarg->length - offset) {
26923 			/* Unlike for negative arguments, some call sites
26924 			 * want length to be clamped if it's positive.
26925 			 */
26926 			if (throw_flag) {
26927 				goto fail_range;
26928 			} else {
26929 				length = h_bufarg->length - offset;
26930 			}
26931 		}
26932 	}
26933 	DUK_ASSERT_DISABLE(length >= 0);  /* unsigned */
26934 	DUK_ASSERT(offset + length <= h_bufarg->length);
26935 
26936 	*out_offset = offset;
26937 	*out_length = length;
26938 	return;
26939 
26940  fail_range:
26941 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARGS);
26942 	DUK_WO_NORETURN(return;);
26943 }
26944 
26945 /* Shared lenient buffer length clamping helper.  No negative indices, no
26946  * element/byte shifting.
26947  */
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)26948 DUK_LOCAL void duk__clamp_startend_nonegidx_noshift(duk_hthread *thr,
26949                                                     duk_int_t buffer_length,
26950                                                     duk_idx_t idx_start,
26951                                                     duk_idx_t idx_end,
26952                                                     duk_int_t *out_start_offset,
26953                                                     duk_int_t *out_end_offset) {
26954 	duk_int_t start_offset;
26955 	duk_int_t end_offset;
26956 
26957 	DUK_ASSERT(out_start_offset != NULL);
26958 	DUK_ASSERT(out_end_offset != NULL);
26959 
26960 	/* undefined coerces to zero which is correct */
26961 	start_offset = duk_to_int_clamped(thr, idx_start, 0, buffer_length);
26962 	if (duk_is_undefined(thr, idx_end)) {
26963 		end_offset = buffer_length;
26964 	} else {
26965 		end_offset = duk_to_int_clamped(thr, idx_end, start_offset, buffer_length);
26966 	}
26967 
26968 	DUK_ASSERT(start_offset >= 0);
26969 	DUK_ASSERT(start_offset <= buffer_length);
26970 	DUK_ASSERT(end_offset >= 0);
26971 	DUK_ASSERT(end_offset <= buffer_length);
26972 	DUK_ASSERT(start_offset <= end_offset);
26973 
26974 	*out_start_offset = start_offset;
26975 	*out_end_offset = end_offset;
26976 }
26977 
26978 /* Shared lenient buffer length clamping helper.  Indices are treated as
26979  * element indices (though output values are byte offsets) which only
26980  * really matters for TypedArray views as other buffer object have a zero
26981  * shift.  Negative indices are counted from end of input slice; crossed
26982  * indices are clamped to zero length; and final indices are clamped
26983  * against input slice.  Used for e.g. ArrayBuffer slice().
26984  */
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)26985 DUK_LOCAL void duk__clamp_startend_negidx_shifted(duk_hthread *thr,
26986                                                   duk_int_t buffer_length,
26987                                                   duk_uint8_t buffer_shift,
26988                                                   duk_idx_t idx_start,
26989                                                   duk_idx_t idx_end,
26990                                                   duk_int_t *out_start_offset,
26991                                                   duk_int_t *out_end_offset) {
26992 	duk_int_t start_offset;
26993 	duk_int_t end_offset;
26994 
26995 	DUK_ASSERT(out_start_offset != NULL);
26996 	DUK_ASSERT(out_end_offset != NULL);
26997 
26998 	buffer_length >>= buffer_shift;  /* as (full) elements */
26999 
27000 	/* Resolve start/end offset as element indices first; arguments
27001 	 * at idx_start/idx_end are element offsets.  Working with element
27002 	 * indices first also avoids potential for wrapping.
27003 	 */
27004 
27005 	start_offset = duk_to_int(thr, idx_start);
27006 	if (start_offset < 0) {
27007 		start_offset = buffer_length + start_offset;
27008 	}
27009 	if (duk_is_undefined(thr, idx_end)) {
27010 		end_offset = buffer_length;
27011 	} else {
27012 		end_offset = duk_to_int(thr, idx_end);
27013 		if (end_offset < 0) {
27014 			end_offset = buffer_length + end_offset;
27015 		}
27016 	}
27017 	/* Note: start_offset/end_offset can still be < 0 here. */
27018 
27019 	if (start_offset < 0) {
27020 		start_offset = 0;
27021 	} else if (start_offset > buffer_length) {
27022 		start_offset = buffer_length;
27023 	}
27024 	if (end_offset < start_offset) {
27025 		end_offset = start_offset;
27026 	} else if (end_offset > buffer_length) {
27027 		end_offset = buffer_length;
27028 	}
27029 	DUK_ASSERT(start_offset >= 0);
27030 	DUK_ASSERT(start_offset <= buffer_length);
27031 	DUK_ASSERT(end_offset >= 0);
27032 	DUK_ASSERT(end_offset <= buffer_length);
27033 	DUK_ASSERT(start_offset <= end_offset);
27034 
27035 	/* Convert indices to byte offsets. */
27036 	start_offset <<= buffer_shift;
27037 	end_offset <<= buffer_shift;
27038 
27039 	*out_start_offset = start_offset;
27040 	*out_end_offset = end_offset;
27041 }
27042 
duk_hbufobj_promote_plain(duk_hthread * thr,duk_idx_t idx)27043 DUK_INTERNAL void duk_hbufobj_promote_plain(duk_hthread *thr, duk_idx_t idx) {
27044 	if (duk_is_buffer(thr, idx)) {
27045 		duk_to_object(thr, idx);
27046 	}
27047 }
27048 
duk_hbufobj_push_uint8array_from_plain(duk_hthread * thr,duk_hbuffer * h_buf)27049 DUK_INTERNAL void duk_hbufobj_push_uint8array_from_plain(duk_hthread *thr, duk_hbuffer *h_buf) {
27050 	/* Push Uint8Array which will share the same underlying buffer as
27051 	 * the plain buffer argument.  Also create an ArrayBuffer with the
27052 	 * same backing for the result .buffer property.
27053 	 */
27054 
27055 	duk_push_hbuffer(thr, h_buf);
27056 	duk_push_buffer_object(thr, -1, 0, (duk_size_t) DUK_HBUFFER_GET_SIZE(h_buf), DUK_BUFOBJ_UINT8ARRAY);
27057 	duk_remove_m2(thr);
27058 
27059 #if 0
27060 	/* More verbose equivalent; maybe useful if e.g. .buffer is omitted. */
27061 	h_bufobj = duk_push_bufobj_raw(thr,
27062 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27063 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27064 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
27065 	                               DUK_BIDX_UINT8ARRAY_PROTOTYPE);
27066 	DUK_ASSERT(h_bufobj != NULL);
27067 	duk__set_bufobj_buffer(thr, h_bufobj, h_buf);
27068 	h_bufobj->is_typedarray = 1;
27069 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27070 
27071 	h_arrbuf = duk_push_bufobj_raw(thr,
27072 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27073 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27074 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27075 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27076 	DUK_ASSERT(h_arrbuf != NULL);
27077 	duk__set_bufobj_buffer(thr, h_arrbuf, h_buf);
27078 	DUK_ASSERT(h_arrbuf->is_typedarray == 0);
27079 	DUK_ASSERT_HBUFOBJ_VALID(h_arrbuf);
27080 
27081 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27082 	h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
27083 	DUK_ASSERT(h_arrbuf != NULL);
27084 	DUK_HBUFOBJ_INCREF(thr, h_arrbuf);
27085 	duk_pop(thr);
27086 #endif
27087 }
27088 
27089 /* 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)27090 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) {
27091 	duk_double_union du;
27092 
27093 	DUK_ASSERT(elem_size > 0);
27094 	duk_memcpy((void *) du.uc, (const void *) p, (size_t) elem_size);
27095 
27096 	switch (h_bufobj->elem_type) {
27097 	case DUK_HBUFOBJ_ELEM_UINT8:
27098 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27099 		duk_push_uint(thr, (duk_uint_t) du.uc[0]);
27100 		break;
27101 	case DUK_HBUFOBJ_ELEM_INT8:
27102 		duk_push_int(thr, (duk_int_t) (duk_int8_t) du.uc[0]);
27103 		break;
27104 	case DUK_HBUFOBJ_ELEM_UINT16:
27105 		duk_push_uint(thr, (duk_uint_t) du.us[0]);
27106 		break;
27107 	case DUK_HBUFOBJ_ELEM_INT16:
27108 		duk_push_int(thr, (duk_int_t) (duk_int16_t) du.us[0]);
27109 		break;
27110 	case DUK_HBUFOBJ_ELEM_UINT32:
27111 		duk_push_uint(thr, (duk_uint_t) du.ui[0]);
27112 		break;
27113 	case DUK_HBUFOBJ_ELEM_INT32:
27114 		duk_push_int(thr, (duk_int_t) (duk_int32_t) du.ui[0]);
27115 		break;
27116 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27117 		duk_push_number(thr, (duk_double_t) du.f[0]);
27118 		break;
27119 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27120 		duk_push_number(thr, (duk_double_t) du.d);
27121 		break;
27122 	default:
27123 		DUK_UNREACHABLE();
27124 	}
27125 }
27126 
27127 /* 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)27128 DUK_INTERNAL void duk_hbufobj_validated_write(duk_hthread *thr, duk_hbufobj *h_bufobj, duk_uint8_t *p, duk_small_uint_t elem_size) {
27129 	duk_double_union du;
27130 
27131 	/* NOTE! Caller must ensure that any side effects from the
27132 	 * coercions below are safe.  If that cannot be guaranteed
27133 	 * (which is normally the case), caller must coerce the
27134 	 * argument using duk_to_number() before any pointer
27135 	 * validations; the result of duk_to_number() always coerces
27136 	 * without side effects here.
27137 	 */
27138 
27139 	switch (h_bufobj->elem_type) {
27140 	case DUK_HBUFOBJ_ELEM_UINT8:
27141 		du.uc[0] = (duk_uint8_t) duk_to_uint32(thr, -1);
27142 		break;
27143 	case DUK_HBUFOBJ_ELEM_UINT8CLAMPED:
27144 		du.uc[0] = (duk_uint8_t) duk_to_uint8clamped(thr, -1);
27145 		break;
27146 	case DUK_HBUFOBJ_ELEM_INT8:
27147 		du.uc[0] = (duk_uint8_t) duk_to_int32(thr, -1);
27148 		break;
27149 	case DUK_HBUFOBJ_ELEM_UINT16:
27150 		du.us[0] = (duk_uint16_t) duk_to_uint32(thr, -1);
27151 		break;
27152 	case DUK_HBUFOBJ_ELEM_INT16:
27153 		du.us[0] = (duk_uint16_t) duk_to_int32(thr, -1);
27154 		break;
27155 	case DUK_HBUFOBJ_ELEM_UINT32:
27156 		du.ui[0] = (duk_uint32_t) duk_to_uint32(thr, -1);
27157 		break;
27158 	case DUK_HBUFOBJ_ELEM_INT32:
27159 		du.ui[0] = (duk_uint32_t) duk_to_int32(thr, -1);
27160 		break;
27161 	case DUK_HBUFOBJ_ELEM_FLOAT32:
27162 		/* A double-to-float cast is undefined behavior in C99 if
27163 		 * the cast is out-of-range, so use a helper.  Example:
27164 		 * runtime error: value -1e+100 is outside the range of representable values of type 'float'
27165 		 */
27166 		du.f[0] = duk_double_to_float_t(duk_to_number_m1(thr));
27167 		break;
27168 	case DUK_HBUFOBJ_ELEM_FLOAT64:
27169 		du.d = (duk_double_t) duk_to_number_m1(thr);
27170 		break;
27171 	default:
27172 		DUK_UNREACHABLE();
27173 	}
27174 
27175 	DUK_ASSERT(elem_size > 0);
27176 	duk_memcpy((void *) p, (const void *) du.uc, (size_t) elem_size);
27177 }
27178 
27179 /* Helper to create a fixed buffer from argument value at index 0.
27180  * Node.js and allocPlain() compatible.
27181  */
duk__hbufobj_fixed_from_argvalue(duk_hthread * thr)27182 DUK_LOCAL duk_hbuffer *duk__hbufobj_fixed_from_argvalue(duk_hthread *thr) {
27183 	duk_int_t len;
27184 	duk_int_t i;
27185 	duk_size_t buf_size;
27186 	duk_uint8_t *buf;
27187 
27188 	switch (duk_get_type(thr, 0)) {
27189 	case DUK_TYPE_NUMBER: {
27190 		len = duk_to_int_clamped(thr, 0, 0, DUK_INT_MAX);
27191 		(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27192 		break;
27193 	}
27194 	case DUK_TYPE_BUFFER: { /* Treat like Uint8Array. */
27195 		goto slow_copy;
27196 	}
27197 	case DUK_TYPE_OBJECT: {
27198 		duk_hobject *h;
27199 		duk_hbufobj *h_bufobj;
27200 
27201 		/* For Node.js Buffers "Passing an ArrayBuffer returns a Buffer
27202 		 * that shares allocated memory with the given ArrayBuffer."
27203 		 * https://nodejs.org/api/buffer.html#buffer_buffer_from_buffer_alloc_and_buffer_allocunsafe
27204 		 */
27205 
27206 		h = duk_known_hobject(thr, 0);
27207 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27208 			DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(h));
27209 			h_bufobj = (duk_hbufobj *) h;
27210 			if (DUK_UNLIKELY(h_bufobj->buf == NULL)) {
27211 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27212 				DUK_WO_NORETURN(return NULL;);
27213 			}
27214 			if (DUK_UNLIKELY(h_bufobj->offset != 0 || h_bufobj->length != DUK_HBUFFER_GET_SIZE(h_bufobj->buf))) {
27215 				/* No support for ArrayBuffers with slice
27216 				 * offset/length.
27217 				 */
27218 				DUK_ERROR_TYPE_INVALID_ARGS(thr);
27219 				DUK_WO_NORETURN(return NULL;);
27220 			}
27221 			duk_push_hbuffer(thr, h_bufobj->buf);
27222 			return h_bufobj->buf;
27223 		}
27224 		goto slow_copy;
27225 	}
27226 	case DUK_TYPE_STRING: {
27227 		/* ignore encoding for now */
27228 		duk_require_hstring_notsymbol(thr, 0);
27229 		duk_dup_0(thr);
27230 		(void) duk_to_buffer(thr, -1, &buf_size);
27231 		break;
27232 	}
27233 	default:
27234 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
27235 		DUK_WO_NORETURN(return NULL;);
27236 	}
27237 
27238  done:
27239 	DUK_ASSERT(duk_is_buffer(thr, -1));
27240 	return duk_known_hbuffer(thr, -1);
27241 
27242  slow_copy:
27243 	/* XXX: fast path for typed arrays and other buffer objects? */
27244 
27245 	(void) duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LENGTH);
27246 	len = duk_to_int_clamped(thr, -1, 0, DUK_INT_MAX);
27247 	duk_pop(thr);
27248 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) len);  /* no zeroing, all indices get initialized */
27249 	for (i = 0; i < len; i++) {
27250 		/* XXX: fast path for array or buffer arguments? */
27251 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27252 		buf[i] = (duk_uint8_t) (duk_to_uint32(thr, -1) & 0xffU);
27253 		duk_pop(thr);
27254 	}
27255 	goto done;
27256 }
27257 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27258 
27259 /*
27260  *  Node.js Buffer constructor
27261  *
27262  *  Node.js Buffers are just Uint8Arrays with internal prototype set to
27263  *  Buffer.prototype so they're handled otherwise the same as Uint8Array.
27264  *  However, the constructor arguments are very different so a separate
27265  *  constructor entry point is used.
27266  */
27267 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_constructor(duk_hthread * thr)27268 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_constructor(duk_hthread *thr) {
27269 	duk_hbuffer *h_buf;
27270 
27271 	h_buf = duk__hbufobj_fixed_from_argvalue(thr);
27272 	DUK_ASSERT(h_buf != NULL);
27273 
27274 	duk_push_buffer_object(thr,
27275 	                       -1,
27276 	                       0,
27277 	                       DUK_HBUFFER_FIXED_GET_SIZE((duk_hbuffer_fixed *) (void *) h_buf),
27278 	                       DUK_BUFOBJ_UINT8ARRAY);
27279 	duk_push_hobject_bidx(thr, DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
27280 	duk_set_prototype(thr, -2);
27281 
27282 	/* XXX: a more direct implementation */
27283 
27284 	return 1;
27285 }
27286 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27287 
27288 /*
27289  *  ArrayBuffer, DataView, and TypedArray constructors
27290  */
27291 
27292 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_constructor(duk_hthread * thr)27293 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_constructor(duk_hthread *thr) {
27294 	duk_hbufobj *h_bufobj;
27295 	duk_hbuffer *h_val;
27296 	duk_int_t len;
27297 
27298 	DUK_ASSERT_CTX_VALID(thr);
27299 
27300 	duk_require_constructor_call(thr);
27301 
27302 	len = duk_to_int(thr, 0);
27303 	if (len < 0) {
27304 		goto fail_length;
27305 	}
27306 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) len);
27307 	h_val = (duk_hbuffer *) duk_known_hbuffer(thr, -1);
27308 
27309 	h_bufobj = duk_push_bufobj_raw(thr,
27310 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27311 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27312 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
27313 	                               DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
27314 	DUK_ASSERT(h_bufobj != NULL);
27315 
27316 	duk__set_bufobj_buffer(thr, h_bufobj, h_val);
27317 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27318 
27319 	return 1;
27320 
27321  fail_length:
27322 	DUK_DCERROR_RANGE_INVALID_LENGTH(thr);
27323 }
27324 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27325 
27326 
27327 /* Format of magic, bits:
27328  *   0...1: elem size shift (0-3)
27329  *   2...5: elem type (DUK_HBUFOBJ_ELEM_xxx)
27330  *
27331  * XXX: add prototype bidx explicitly to magic instead of using a mapping?
27332  */
27333 
27334 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_constructor(duk_hthread * thr)27335 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27336 	duk_tval *tv;
27337 	duk_hobject *h_obj;
27338 	duk_hbufobj *h_bufobj = NULL;
27339 	duk_hbufobj *h_bufarg = NULL;
27340 	duk_hbuffer *h_val;
27341 	duk_small_uint_t magic;
27342 	duk_small_uint_t shift;
27343 	duk_small_uint_t elem_type;
27344 	duk_small_uint_t elem_size;
27345 	duk_small_uint_t class_num;
27346 	duk_small_uint_t proto_bidx;
27347 	duk_uint_t align_mask;
27348 	duk_uint_t elem_length;
27349 	duk_int_t elem_length_signed;
27350 	duk_uint_t byte_length;
27351 	duk_small_uint_t copy_mode;
27352 
27353 	/* XXX: The same copy helpers could be shared with at least some
27354 	 * buffer functions.
27355 	 */
27356 
27357 	duk_require_constructor_call(thr);
27358 
27359 	/* We could fit built-in index into magic but that'd make the magic
27360 	 * number dependent on built-in numbering (genbuiltins.py doesn't
27361 	 * handle that yet).  So map both class and prototype from the
27362 	 * element type.
27363 	 */
27364 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27365 	shift = magic & 0x03U;               /* bits 0...1: shift */
27366 	elem_type = (magic >> 2) & 0x0fU;    /* bits 2...5: type */
27367 	elem_size = 1U << shift;
27368 	align_mask = elem_size - 1;
27369 	DUK_ASSERT(elem_type < sizeof(duk__buffer_proto_from_elemtype) / sizeof(duk_uint8_t));
27370 	proto_bidx = duk__buffer_proto_from_elemtype[elem_type];
27371 	DUK_ASSERT(proto_bidx < DUK_NUM_BUILTINS);
27372 	DUK_ASSERT(elem_type < sizeof(duk__buffer_class_from_elemtype) / sizeof(duk_uint8_t));
27373 	class_num = duk__buffer_class_from_elemtype[elem_type];
27374 
27375 	DUK_DD(DUK_DDPRINT("typedarray constructor, magic=%d, shift=%d, elem_type=%d, "
27376 	                   "elem_size=%d, proto_bidx=%d, class_num=%d",
27377 	                   (int) magic, (int) shift, (int) elem_type, (int) elem_size,
27378 	                   (int) proto_bidx, (int) class_num));
27379 
27380 	/* Argument variants.  When the argument is an ArrayBuffer a view to
27381 	 * the same buffer is created; otherwise a new ArrayBuffer is always
27382 	 * created.
27383 	 */
27384 
27385 	/* XXX: initial iteration to treat a plain buffer like an ArrayBuffer:
27386 	 * coerce to an ArrayBuffer object and use that as .buffer.  The underlying
27387 	 * buffer will be the same but result .buffer !== inputPlainBuffer.
27388 	 */
27389 	duk_hbufobj_promote_plain(thr, 0);
27390 
27391 	tv = duk_get_tval(thr, 0);
27392 	DUK_ASSERT(tv != NULL);  /* arg count */
27393 	if (DUK_TVAL_IS_OBJECT(tv)) {
27394 		h_obj = DUK_TVAL_GET_OBJECT(tv);
27395 		DUK_ASSERT(h_obj != NULL);
27396 
27397 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27398 			/* ArrayBuffer: unlike any other argument variant, create
27399 			 * a view into the existing buffer.
27400 			 */
27401 
27402 			duk_int_t byte_offset_signed;
27403 			duk_uint_t byte_offset;
27404 
27405 			h_bufarg = (duk_hbufobj *) h_obj;
27406 
27407 			byte_offset_signed = duk_to_int(thr, 1);
27408 			if (byte_offset_signed < 0) {
27409 				goto fail_arguments;
27410 			}
27411 			byte_offset = (duk_uint_t) byte_offset_signed;
27412 			if (byte_offset > h_bufarg->length ||
27413 			    (byte_offset & align_mask) != 0) {
27414 				/* Must be >= 0 and multiple of element size. */
27415 				goto fail_arguments;
27416 			}
27417 			if (duk_is_undefined(thr, 2)) {
27418 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27419 				byte_length = h_bufarg->length - byte_offset;
27420 				if ((byte_length & align_mask) != 0) {
27421 					/* Must be element size multiple from
27422 					 * start offset to end of buffer.
27423 					 */
27424 					goto fail_arguments;
27425 				}
27426 				elem_length = (byte_length >> shift);
27427 			} else {
27428 				elem_length_signed = duk_to_int(thr, 2);
27429 				if (elem_length_signed < 0) {
27430 					goto fail_arguments;
27431 				}
27432 				elem_length = (duk_uint_t) elem_length_signed;
27433 				byte_length = elem_length << shift;
27434 				if ((byte_length >> shift) != elem_length) {
27435 					/* Byte length would overflow. */
27436 					/* XXX: easier check with less code? */
27437 					goto fail_arguments;
27438 				}
27439 				DUK_ASSERT(h_bufarg->length >= byte_offset);
27440 				if (byte_length > h_bufarg->length - byte_offset) {
27441 					/* Not enough data. */
27442 					goto fail_arguments;
27443 				}
27444 			}
27445 			DUK_UNREF(elem_length);
27446 			DUK_ASSERT_DISABLE(byte_offset >= 0);
27447 			DUK_ASSERT(byte_offset <= h_bufarg->length);
27448 			DUK_ASSERT_DISABLE(byte_length >= 0);
27449 			DUK_ASSERT(byte_offset + byte_length <= h_bufarg->length);
27450 			DUK_ASSERT((elem_length << shift) == byte_length);
27451 
27452 			h_bufobj = duk_push_bufobj_raw(thr,
27453 			                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27454 			                               DUK_HOBJECT_FLAG_BUFOBJ |
27455 			                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27456 			                               (duk_small_int_t) proto_bidx);
27457 			h_val = h_bufarg->buf;
27458 			if (h_val == NULL) {
27459 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27460 			}
27461 			h_bufobj->buf = h_val;
27462 			DUK_HBUFFER_INCREF(thr, h_val);
27463 			h_bufobj->offset = h_bufarg->offset + byte_offset;
27464 			h_bufobj->length = byte_length;
27465 			h_bufobj->shift = (duk_uint8_t) shift;
27466 			h_bufobj->elem_type = (duk_uint8_t) elem_type;
27467 			h_bufobj->is_typedarray = 1;
27468 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27469 
27470 			/* Set .buffer to the argument ArrayBuffer. */
27471 			DUK_ASSERT(h_bufobj->buf_prop == NULL);
27472 			h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27473 			DUK_ASSERT(h_bufarg != NULL);
27474 			DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27475 			return 1;
27476 		} else if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27477 			/* TypedArray (or other non-ArrayBuffer duk_hbufobj).
27478 			 * Conceptually same behavior as for an Array-like argument,
27479 			 * with a few fast paths.
27480 			 */
27481 
27482 			h_bufarg = (duk_hbufobj *) h_obj;
27483 			DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
27484 			elem_length_signed = (duk_int_t) (h_bufarg->length >> h_bufarg->shift);
27485 			if (h_bufarg->buf == NULL) {
27486 				DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27487 			}
27488 
27489 			/* Select copy mode.  Must take into account element
27490 			 * compatibility and validity of the underlying source
27491 			 * buffer.
27492 			 */
27493 
27494 			DUK_DDD(DUK_DDDPRINT("selecting copy mode for bufobj arg, "
27495 			                     "src byte_length=%ld, src shift=%d, "
27496 			                     "src/dst elem_length=%ld; "
27497 			                     "dst shift=%d -> dst byte_length=%ld",
27498 			                     (long) h_bufarg->length, (int) h_bufarg->shift,
27499 			                     (long) elem_length_signed, (int) shift,
27500 			                     (long) (elem_length_signed << shift)));
27501 
27502 			copy_mode = 2;  /* default is explicit index read/write copy */
27503 #if !defined(DUK_USE_PREFER_SIZE)
27504 			/* With a size optimized build copy_mode 2 is enough.
27505 			 * Modes 0 and 1 are faster but conceptually the same.
27506 			 */
27507 			DUK_ASSERT(elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
27508 			if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
27509 				if ((duk__buffer_elemtype_copy_compatible[elem_type] & (1 << h_bufarg->elem_type)) != 0) {
27510 					DUK_DDD(DUK_DDDPRINT("source/target are copy compatible, memcpy"));
27511 					DUK_ASSERT(shift == h_bufarg->shift);  /* byte sizes will match */
27512 					copy_mode = 0;
27513 				} else {
27514 					DUK_DDD(DUK_DDDPRINT("source/target not copy compatible but valid, fast copy"));
27515 					copy_mode = 1;
27516 				}
27517 			}
27518 #endif  /* !DUK_USE_PREFER_SIZE */
27519 		} else {
27520 			/* Array or Array-like */
27521 			elem_length_signed = (duk_int_t) duk_get_length(thr, 0);
27522 			copy_mode = 2;
27523 		}
27524 	} else {
27525 		/* Non-object argument is simply int coerced, matches
27526 		 * V8 behavior (except for "null", which we coerce to
27527 		 * 0 but V8 TypeErrors).
27528 		 */
27529 		elem_length_signed = duk_to_int(thr, 0);
27530 		copy_mode = 3;
27531 	}
27532 	if (elem_length_signed < 0) {
27533 		goto fail_arguments;
27534 	}
27535 	elem_length = (duk_uint_t) elem_length_signed;
27536 	byte_length = (duk_uint_t) (elem_length << shift);
27537 	if ((byte_length >> shift) != elem_length) {
27538 		/* Byte length would overflow. */
27539 		/* XXX: easier check with less code? */
27540 		goto fail_arguments;
27541 	}
27542 
27543 	DUK_DDD(DUK_DDDPRINT("elem_length=%ld, byte_length=%ld",
27544 	                     (long) elem_length, (long) byte_length));
27545 
27546 	/* ArrayBuffer argument is handled specially above; the rest of the
27547 	 * argument variants are handled by shared code below.
27548 	 *
27549 	 * ArrayBuffer in h_bufobj->buf_prop is intentionally left unset.
27550 	 * It will be automatically created by the .buffer accessor on
27551 	 * first access.
27552 	 */
27553 
27554 	/* Push the resulting view object on top of a plain fixed buffer. */
27555 	(void) duk_push_fixed_buffer(thr, byte_length);
27556 	h_val = duk_known_hbuffer(thr, -1);
27557 	DUK_ASSERT(h_val != NULL);
27558 
27559 	h_bufobj = duk_push_bufobj_raw(thr,
27560 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27561 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27562 	                               DUK_HOBJECT_CLASS_AS_FLAGS(class_num),
27563 	                               (duk_small_int_t) proto_bidx);
27564 
27565 	h_bufobj->buf = h_val;
27566 	DUK_HBUFFER_INCREF(thr, h_val);
27567 	DUK_ASSERT(h_bufobj->offset == 0);
27568 	h_bufobj->length = byte_length;
27569 	h_bufobj->shift = (duk_uint8_t) shift;
27570 	h_bufobj->elem_type = (duk_uint8_t) elem_type;
27571 	h_bufobj->is_typedarray = 1;
27572 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27573 
27574 	/* Copy values, the copy method depends on the arguments.
27575 	 *
27576 	 * Copy mode decision may depend on the validity of the underlying
27577 	 * buffer of the source argument; there must be no harmful side effects
27578 	 * from there to here for copy_mode to still be valid.
27579 	 */
27580 	DUK_DDD(DUK_DDDPRINT("copy mode: %d", (int) copy_mode));
27581 	switch (copy_mode) {
27582 		/* Copy modes 0 and 1 can be omitted in size optimized build,
27583 		 * copy mode 2 handles them (but more slowly).
27584 		 */
27585 #if !defined(DUK_USE_PREFER_SIZE)
27586 	case 0: {
27587 		/* Use byte copy. */
27588 
27589 		duk_uint8_t *p_src;
27590 		duk_uint8_t *p_dst;
27591 
27592 		DUK_ASSERT(h_bufobj != NULL);
27593 		DUK_ASSERT(h_bufobj->buf != NULL);
27594 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27595 		DUK_ASSERT(h_bufarg != NULL);
27596 		DUK_ASSERT(h_bufarg->buf != NULL);
27597 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27598 
27599 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27600 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27601 
27602 		DUK_DDD(DUK_DDDPRINT("using memcpy: p_src=%p, p_dst=%p, byte_length=%ld",
27603 		                     (void *) p_src, (void *) p_dst, (long) byte_length));
27604 
27605 		duk_memcpy_unsafe((void *) p_dst, (const void *) p_src, (size_t) byte_length);
27606 		break;
27607 	}
27608 	case 1: {
27609 		/* Copy values through direct validated reads and writes. */
27610 
27611 		duk_small_uint_t src_elem_size;
27612 		duk_small_uint_t dst_elem_size;
27613 		duk_uint8_t *p_src;
27614 		duk_uint8_t *p_src_end;
27615 		duk_uint8_t *p_dst;
27616 
27617 		DUK_ASSERT(h_bufobj != NULL);
27618 		DUK_ASSERT(h_bufobj->buf != NULL);
27619 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufobj));
27620 		DUK_ASSERT(h_bufarg != NULL);
27621 		DUK_ASSERT(h_bufarg->buf != NULL);
27622 		DUK_ASSERT(DUK_HBUFOBJ_VALID_SLICE(h_bufarg));
27623 
27624 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
27625 		dst_elem_size = elem_size;
27626 
27627 		p_src = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
27628 		p_dst = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj);
27629 		p_src_end = p_src + h_bufarg->length;
27630 
27631 		DUK_DDD(DUK_DDDPRINT("using fast copy: p_src=%p, p_src_end=%p, p_dst=%p, "
27632 		                     "src_elem_size=%d, dst_elem_size=%d",
27633 		                     (void *) p_src, (void *) p_src_end, (void *) p_dst,
27634 		                     (int) src_elem_size, (int) dst_elem_size));
27635 
27636 		while (p_src != p_src_end) {
27637 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
27638 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
27639 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
27640 			/* A validated read() is always a number, so it's write coercion
27641 			 * is always side effect free an won't invalidate pointers etc.
27642 			 */
27643 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
27644 			duk_hbufobj_validated_write(thr, h_bufobj, p_dst, dst_elem_size);
27645 			duk_pop(thr);
27646 			p_src += src_elem_size;
27647 			p_dst += dst_elem_size;
27648 		}
27649 		break;
27650 	}
27651 #endif  /* !DUK_USE_PREFER_SIZE */
27652 	case 2: {
27653 		/* Copy values by index reads and writes.  Let virtual
27654 		 * property handling take care of coercion.
27655 		 */
27656 		duk_uint_t i;
27657 
27658 		DUK_DDD(DUK_DDDPRINT("using slow copy"));
27659 
27660 		for (i = 0; i < elem_length; i++) {
27661 			duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
27662 			duk_put_prop_index(thr, -2, (duk_uarridx_t) i);
27663 		}
27664 		break;
27665 	}
27666 	default:
27667 	case 3: {
27668 		/* No copy, leave zero bytes in the buffer.  There's no
27669 		 * ambiguity with Float32/Float64 because zero bytes also
27670 		 * represent 0.0.
27671 		 */
27672 
27673 		DUK_DDD(DUK_DDDPRINT("using no copy"));
27674 		break;
27675 	}
27676 	}
27677 
27678 	return 1;
27679 
27680  fail_arguments:
27681 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27682 }
27683 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27684 /* When bufferobject support is disabled, new Uint8Array() could still be
27685  * supported to create a plain fixed buffer.  Disabled for now.
27686  */
27687 #if 0
27688 DUK_INTERNAL duk_ret_t duk_bi_typedarray_constructor(duk_hthread *thr) {
27689 	duk_int_t elem_length_signed;
27690 	duk_uint_t byte_length;
27691 
27692 	/* XXX: The same copy helpers could be shared with at least some
27693 	 * buffer functions.
27694 	 */
27695 
27696 	duk_require_constructor_call(thr);
27697 
27698 	elem_length_signed = duk_require_int(thr, 0);
27699 	if (elem_length_signed < 0) {
27700 		goto fail_arguments;
27701 	}
27702 	byte_length = (duk_uint_t) elem_length_signed;
27703 
27704 	(void) duk_push_fixed_buffer_zero(thr, (duk_size_t) byte_length);
27705 	return 1;
27706 
27707  fail_arguments:
27708 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
27709 }
27710 #endif  /* 0 */
27711 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27712 
27713 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_dataview_constructor(duk_hthread * thr)27714 DUK_INTERNAL duk_ret_t duk_bi_dataview_constructor(duk_hthread *thr) {
27715 	duk_hbufobj *h_bufarg;
27716 	duk_hbufobj *h_bufobj;
27717 	duk_hbuffer *h_val;
27718 	duk_uint_t offset;
27719 	duk_uint_t length;
27720 
27721 	duk_require_constructor_call(thr);
27722 
27723 	h_bufarg = duk__require_bufobj_value(thr, 0);
27724 	DUK_ASSERT(h_bufarg != NULL);
27725 	if (DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufarg) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
27726 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27727 	}
27728 
27729 	duk__resolve_offset_opt_length(thr, h_bufarg, 1, 2, &offset, &length, 1 /*throw_flag*/);
27730 	DUK_ASSERT(offset <= h_bufarg->length);
27731 	DUK_ASSERT(offset + length <= h_bufarg->length);
27732 
27733 	h_bufobj = duk_push_bufobj_raw(thr,
27734 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
27735 	                               DUK_HOBJECT_FLAG_BUFOBJ |
27736 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATAVIEW),
27737 	                               DUK_BIDX_DATAVIEW_PROTOTYPE);
27738 
27739 	h_val = h_bufarg->buf;
27740 	if (h_val == NULL) {
27741 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27742 	}
27743 	h_bufobj->buf = h_val;
27744 	DUK_HBUFFER_INCREF(thr, h_val);
27745 	h_bufobj->offset = h_bufarg->offset + offset;
27746 	h_bufobj->length = length;
27747 	DUK_ASSERT(h_bufobj->shift == 0);
27748 	DUK_ASSERT(h_bufobj->elem_type == DUK_HBUFOBJ_ELEM_UINT8);
27749 	DUK_ASSERT(h_bufobj->is_typedarray == 0);
27750 
27751 	DUK_ASSERT(h_bufobj->buf_prop == NULL);
27752 	h_bufobj->buf_prop = (duk_hobject *) h_bufarg;
27753 	DUK_ASSERT(h_bufarg != NULL);
27754 	DUK_HBUFOBJ_INCREF(thr, h_bufarg);
27755 
27756 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
27757 	return 1;
27758 }
27759 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27760 
27761 /*
27762  *  ArrayBuffer.isView()
27763  */
27764 
27765 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_arraybuffer_isview(duk_hthread * thr)27766 DUK_INTERNAL duk_ret_t duk_bi_arraybuffer_isview(duk_hthread *thr) {
27767 	duk_hobject *h_obj;
27768 	duk_bool_t ret = 0;
27769 
27770 	if (duk_is_buffer(thr, 0)) {
27771 		ret = 1;
27772 	} else {
27773 		h_obj = duk_get_hobject(thr, 0);
27774 		if (h_obj != NULL && DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
27775 			/* DataView needs special casing: ArrayBuffer.isView() is
27776 			 * true, but ->is_typedarray is 0.
27777 			 */
27778 			ret = ((duk_hbufobj *) h_obj)->is_typedarray ||
27779 			      (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_DATAVIEW);
27780 		}
27781 	}
27782 	duk_push_boolean(thr, ret);
27783 	return 1;
27784 }
27785 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27786 
27787 /*
27788  *  Uint8Array.allocPlain()
27789  */
27790 
27791 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_allocplain(duk_hthread * thr)27792 DUK_INTERNAL duk_ret_t duk_bi_uint8array_allocplain(duk_hthread *thr) {
27793 	duk__hbufobj_fixed_from_argvalue(thr);
27794 	return 1;
27795 }
27796 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27797 
27798 /*
27799  *  Uint8Array.plainOf()
27800  */
27801 
27802 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_uint8array_plainof(duk_hthread * thr)27803 DUK_INTERNAL duk_ret_t duk_bi_uint8array_plainof(duk_hthread *thr) {
27804 	duk_hbufobj *h_bufobj;
27805 
27806 #if !defined(DUK_USE_PREFER_SIZE)
27807 	/* Avoid churn if argument is already a plain buffer. */
27808 	if (duk_is_buffer(thr, 0)) {
27809 		return 1;
27810 	}
27811 #endif
27812 
27813 	/* Promotes plain buffers to ArrayBuffers, so for a plain buffer
27814 	 * argument we'll create a pointless temporary (but still work
27815 	 * correctly).
27816 	 */
27817 	h_bufobj = duk__require_bufobj_value(thr, 0);
27818 	if (h_bufobj->buf == NULL) {
27819 		duk_push_undefined(thr);
27820 	} else {
27821 		duk_push_hbuffer(thr, h_bufobj->buf);
27822 	}
27823 	return 1;
27824 }
27825 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27826 
27827 /*
27828  *  Node.js Buffer: toString([encoding], [start], [end])
27829  */
27830 
27831 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tostring(duk_hthread * thr)27832 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tostring(duk_hthread *thr) {
27833 	duk_hbufobj *h_this;
27834 	duk_int_t start_offset, end_offset;
27835 	duk_uint8_t *buf_slice;
27836 	duk_size_t slice_length;
27837 
27838 	h_this = duk__get_bufobj_this(thr);
27839 	if (h_this == NULL) {
27840 		/* XXX: happens e.g. when evaluating: String(Buffer.prototype). */
27841 		duk_push_literal(thr, "[object Object]");
27842 		return 1;
27843 	}
27844 	DUK_ASSERT_HBUFOBJ_VALID(h_this);
27845 
27846 	/* Ignore encoding for now. */
27847 
27848 	duk__clamp_startend_nonegidx_noshift(thr,
27849 	                                     (duk_int_t) h_this->length,
27850 	                                     1 /*idx_start*/,
27851 	                                     2 /*idx_end*/,
27852 	                                     &start_offset,
27853 	                                     &end_offset);
27854 
27855 	slice_length = (duk_size_t) (end_offset - start_offset);
27856 	buf_slice = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, slice_length);  /* all bytes initialized below */
27857 	DUK_ASSERT(buf_slice != NULL);
27858 
27859 	/* Neutered or uncovered, TypeError. */
27860 	if (h_this->buf == NULL ||
27861 	    !DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length)) {
27862 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
27863 	}
27864 
27865 	/* XXX: ideally we wouldn't make a copy but a view into the buffer for the
27866 	 * decoding process.  Or the decoding helper could be changed to accept
27867 	 * the slice info (a buffer pointer is NOT a good approach because guaranteeing
27868 	 * its stability is difficult).
27869 	 */
27870 
27871 	DUK_ASSERT(DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, (duk_size_t) start_offset + slice_length));
27872 	duk_memcpy_unsafe((void *) buf_slice,
27873 	                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
27874 	                  (size_t) slice_length);
27875 
27876 	/* Use the equivalent of: new TextEncoder().encode(this) to convert the
27877 	 * string.  Result will be valid UTF-8; non-CESU-8 inputs are currently
27878 	 * interpreted loosely.  Value stack convention is a bit odd for now.
27879 	 */
27880 	duk_replace(thr, 0);
27881 	duk_set_top(thr, 1);
27882 	return duk_textdecoder_decode_utf8_nodejs(thr);
27883 }
27884 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27885 
27886 /*
27887  *  Node.js Buffer.prototype: toJSON()
27888  */
27889 
27890 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_tojson(duk_hthread * thr)27891 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_tojson(duk_hthread *thr) {
27892 	duk_hbufobj *h_this;
27893 	duk_uint8_t *buf;
27894 	duk_uint_t i, n;
27895 	duk_tval *tv;
27896 
27897 	h_this = duk__require_bufobj_this(thr);
27898 	DUK_ASSERT(h_this != NULL);
27899 
27900 	if (h_this->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_this)) {
27901 		/* Serialize uncovered backing buffer as a null; doesn't
27902 		 * really matter as long we're memory safe.
27903 		 */
27904 		duk_push_null(thr);
27905 		return 1;
27906 	}
27907 
27908 	duk_push_object(thr);
27909 	duk_push_hstring_stridx(thr, DUK_STRIDX_UC_BUFFER);
27910 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_TYPE);
27911 
27912 	/* XXX: uninitialized would be OK */
27913 	DUK_ASSERT_DISABLE((duk_size_t) h_this->length <= (duk_size_t) DUK_UINT32_MAX);
27914 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) h_this->length);  /* XXX: needs revision with >4G buffers */
27915 
27916 	DUK_ASSERT(h_this->buf != NULL);
27917 	buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
27918 	for (i = 0, n = h_this->length; i < n; i++) {
27919 		DUK_TVAL_SET_U32(tv + i, (duk_uint32_t) buf[i]);  /* no need for decref or incref */
27920 	}
27921 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_DATA);
27922 
27923 	return 1;
27924 }
27925 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27926 
27927 /*
27928  *  Node.js Buffer.prototype.equals()
27929  *  Node.js Buffer.prototype.compare()
27930  *  Node.js Buffer.compare()
27931  */
27932 
27933 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_buffer_compare_shared(duk_hthread * thr)27934 DUK_INTERNAL duk_ret_t duk_bi_buffer_compare_shared(duk_hthread *thr) {
27935 	duk_small_uint_t magic;
27936 	duk_hbufobj *h_bufarg1;
27937 	duk_hbufobj *h_bufarg2;
27938 	duk_small_int_t comp_res;
27939 
27940 	/* XXX: keep support for plain buffers and non-Node.js buffers? */
27941 
27942 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
27943 	if (magic & 0x02U) {
27944 		/* Static call style. */
27945 		h_bufarg1 = duk__require_bufobj_value(thr, 0);
27946 		h_bufarg2 = duk__require_bufobj_value(thr, 1);
27947 	} else {
27948 		h_bufarg1 = duk__require_bufobj_this(thr);
27949 		h_bufarg2 = duk__require_bufobj_value(thr, 0);
27950 	}
27951 	DUK_ASSERT(h_bufarg1 != NULL);
27952 	DUK_ASSERT(h_bufarg2 != NULL);
27953 
27954 	/* We want to compare the slice/view areas of the arguments.
27955 	 * If either slice/view is invalid (underlying buffer is shorter)
27956 	 * ensure equals() is false, but otherwise the only thing that
27957 	 * matters is to be memory safe.
27958 	 */
27959 
27960 	if (DUK_HBUFOBJ_VALID_SLICE(h_bufarg1) &&
27961 	    DUK_HBUFOBJ_VALID_SLICE(h_bufarg2)) {
27962 		comp_res = duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg1->buf) + h_bufarg1->offset,
27963 		                               (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufarg2->buf) + h_bufarg2->offset,
27964 		                               (duk_size_t) h_bufarg1->length,
27965 		                               (duk_size_t) h_bufarg2->length);
27966 	} else {
27967 		comp_res = -1;  /* either nonzero value is ok */
27968 	}
27969 
27970 	if (magic & 0x01U) {
27971 		/* compare: similar to string comparison but for buffer data. */
27972 		duk_push_int(thr, comp_res);
27973 	} else {
27974 		/* equals */
27975 		duk_push_boolean(thr, (comp_res == 0));
27976 	}
27977 
27978 	return 1;
27979 }
27980 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
27981 
27982 /*
27983  *  Node.js Buffer.prototype.fill()
27984  */
27985 
27986 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_fill(duk_hthread * thr)27987 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_fill(duk_hthread *thr) {
27988 	duk_hbufobj *h_this;
27989 	const duk_uint8_t *fill_str_ptr;
27990 	duk_size_t fill_str_len;
27991 	duk_uint8_t fill_value;
27992 	duk_int_t fill_offset;
27993 	duk_int_t fill_end;
27994 	duk_size_t fill_length;
27995 	duk_uint8_t *p;
27996 
27997 	h_this = duk__require_bufobj_this(thr);
27998 	DUK_ASSERT(h_this != NULL);
27999 	if (h_this->buf == NULL) {
28000 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28001 	}
28002 
28003 	/* [ value offset end ] */
28004 
28005 	if (duk_is_string_notsymbol(thr, 0)) {
28006 		fill_str_ptr = (const duk_uint8_t *) duk_get_lstring(thr, 0, &fill_str_len);
28007 		DUK_ASSERT(fill_str_ptr != NULL);
28008 	} else {
28009 		/* Symbols get ToNumber() coerced and cause TypeError. */
28010 		fill_value = (duk_uint8_t) duk_to_uint32(thr, 0);
28011 		fill_str_ptr = (const duk_uint8_t *) &fill_value;
28012 		fill_str_len = 1;
28013 	}
28014 
28015 	/* Fill offset handling is more lenient than in Node.js. */
28016 
28017 	duk__clamp_startend_nonegidx_noshift(thr,
28018 	                                     (duk_int_t) h_this->length,
28019 	                                     1 /*idx_start*/,
28020 	                                     2 /*idx_end*/,
28021 	                                     &fill_offset,
28022 	                                     &fill_end);
28023 
28024 	DUK_DDD(DUK_DDDPRINT("fill: fill_value=%02x, fill_offset=%ld, fill_end=%ld, view length=%ld",
28025 	                     (unsigned int) fill_value, (long) fill_offset, (long) fill_end, (long) h_this->length));
28026 
28027 	DUK_ASSERT(fill_end - fill_offset >= 0);
28028 	DUK_ASSERT(h_this->buf != NULL);
28029 
28030 	p = (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + fill_offset);
28031 	fill_length = (duk_size_t) (fill_end - fill_offset);
28032 	if (fill_str_len == 1) {
28033 		/* Handle single character fills as memset() even when
28034 		 * the fill data comes from a one-char argument.
28035 		 */
28036 		duk_memset_unsafe((void *) p, (int) fill_str_ptr[0], (size_t) fill_length);
28037 	} else if (fill_str_len > 1) {
28038 		duk_size_t i, n, t;
28039 
28040 		for (i = 0, n = (duk_size_t) (fill_end - fill_offset), t = 0; i < n; i++) {
28041 			p[i] = fill_str_ptr[t++];
28042 			if (t >= fill_str_len) {
28043 				t = 0;
28044 			}
28045 		}
28046 	} else {
28047 		DUK_DDD(DUK_DDDPRINT("zero size fill pattern, ignore silently"));
28048 	}
28049 
28050 	/* Return the Buffer to allow chaining: b.fill(0x11).fill(0x22, 3, 5).toString() */
28051 	duk_push_this(thr);
28052 	return 1;
28053 }
28054 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28055 
28056 /*
28057  *  Node.js Buffer.prototype.write(string, [offset], [length], [encoding])
28058  */
28059 
28060 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_write(duk_hthread * thr)28061 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_write(duk_hthread *thr) {
28062 	duk_hbufobj *h_this;
28063 	duk_uint_t offset;
28064 	duk_uint_t length;
28065 	const duk_uint8_t *str_data;
28066 	duk_size_t str_len;
28067 
28068 	/* XXX: very inefficient support for plain buffers */
28069 	h_this = duk__require_bufobj_this(thr);
28070 	DUK_ASSERT(h_this != NULL);
28071 
28072 	/* Argument must be a string, e.g. a buffer is not allowed. */
28073 	str_data = (const duk_uint8_t *) duk_require_lstring_notsymbol(thr, 0, &str_len);
28074 
28075 	duk__resolve_offset_opt_length(thr, h_this, 1, 2, &offset, &length, 0 /*throw_flag*/);
28076 	DUK_ASSERT(offset <= h_this->length);
28077 	DUK_ASSERT(offset + length <= h_this->length);
28078 
28079 	/* XXX: encoding is ignored now. */
28080 
28081 	if (length > str_len) {
28082 		length = (duk_uint_t) str_len;
28083 	}
28084 
28085 	if (DUK_HBUFOBJ_VALID_SLICE(h_this)) {
28086 		/* Cannot overlap. */
28087 		duk_memcpy_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset),
28088 		                  (const void *) str_data,
28089 		                  (size_t) length);
28090 	} else {
28091 		DUK_DDD(DUK_DDDPRINT("write() target buffer is not covered, silent ignore"));
28092 	}
28093 
28094 	duk_push_uint(thr, length);
28095 	return 1;
28096 }
28097 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28098 
28099 /*
28100  *  Node.js Buffer.prototype.copy()
28101  */
28102 
28103 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_copy(duk_hthread * thr)28104 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_copy(duk_hthread *thr) {
28105 	duk_hbufobj *h_this;
28106 	duk_hbufobj *h_bufarg;
28107 	duk_int_t source_length;
28108 	duk_int_t target_length;
28109 	duk_int_t target_start, source_start, source_end;
28110 	duk_uint_t target_ustart, source_ustart, source_uend;
28111 	duk_uint_t copy_size = 0;
28112 
28113 	/* [ targetBuffer targetStart sourceStart sourceEnd ] */
28114 
28115 	h_this = duk__require_bufobj_this(thr);
28116 	h_bufarg = duk__require_bufobj_value(thr, 0);
28117 	DUK_ASSERT(h_this != NULL);
28118 	DUK_ASSERT(h_bufarg != NULL);
28119 	source_length = (duk_int_t) h_this->length;
28120 	target_length = (duk_int_t) h_bufarg->length;
28121 
28122 	target_start = duk_to_int(thr, 1);
28123 	source_start = duk_to_int(thr, 2);
28124 	if (duk_is_undefined(thr, 3)) {
28125 		source_end = source_length;
28126 	} else {
28127 		source_end = duk_to_int(thr, 3);
28128 	}
28129 
28130 	DUK_DDD(DUK_DDDPRINT("checking copy args: target_start=%ld, target_length=%ld, "
28131 	                     "source_start=%ld, source_end=%ld, source_length=%ld",
28132 	                     (long) target_start, (long) h_bufarg->length,
28133 	                     (long) source_start, (long) source_end, (long) source_length));
28134 
28135 	/* This behavior mostly mimics Node.js now. */
28136 
28137 	if (source_start < 0 || source_end < 0 || target_start < 0) {
28138 		/* Negative offsets cause a RangeError. */
28139 		goto fail_bounds;
28140 	}
28141 	source_ustart = (duk_uint_t) source_start;
28142 	source_uend = (duk_uint_t) source_end;
28143 	target_ustart = (duk_uint_t) target_start;
28144 	if (source_ustart >= source_uend ||  /* crossed offsets or zero size */
28145 	    source_ustart >= (duk_uint_t) source_length ||  /* source out-of-bounds (but positive) */
28146 	    target_ustart >= (duk_uint_t) target_length) {  /* target out-of-bounds (but positive) */
28147 		goto silent_ignore;
28148 	}
28149 	if (source_uend >= (duk_uint_t) source_length) {
28150 		/* Source end clamped silently to available length. */
28151 		source_uend = (duk_uint_t) source_length;
28152 	}
28153 	copy_size = source_uend - source_ustart;
28154 	if (target_ustart + copy_size > (duk_uint_t) target_length) {
28155 		/* Clamp to target's end if too long.
28156 		 *
28157 		 * NOTE: there's no overflow possibility in the comparison;
28158 		 * both target_ustart and copy_size are >= 0 and based on
28159 		 * values in duk_int_t range.  Adding them as duk_uint_t
28160 		 * values is then guaranteed not to overflow.
28161 		 */
28162 		DUK_ASSERT(target_ustart + copy_size >= target_ustart);  /* no overflow */
28163 		DUK_ASSERT(target_ustart + copy_size >= copy_size);  /* no overflow */
28164 		copy_size = (duk_uint_t) target_length - target_ustart;
28165 	}
28166 
28167 	DUK_DDD(DUK_DDDPRINT("making copy: target_ustart=%lu source_ustart=%lu copy_size=%lu",
28168 	                     (unsigned long) target_ustart, (unsigned long) source_ustart,
28169 	                     (unsigned long) copy_size));
28170 
28171 	DUK_ASSERT(copy_size >= 1);
28172 	DUK_ASSERT(source_ustart <= (duk_uint_t) source_length);
28173 	DUK_ASSERT(source_ustart + copy_size <= (duk_uint_t) source_length);
28174 	DUK_ASSERT(target_ustart <= (duk_uint_t) target_length);
28175 	DUK_ASSERT(target_ustart + copy_size <= (duk_uint_t) target_length);
28176 
28177 	/* Ensure copy is covered by underlying buffers. */
28178 	DUK_ASSERT(h_bufarg->buf != NULL);  /* length check */
28179 	DUK_ASSERT(h_this->buf != NULL);    /* length check */
28180 	if (DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufarg, target_ustart + copy_size) &&
28181 	    DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, source_ustart + copy_size)) {
28182 		/* Must use memmove() because copy area may overlap (source and target
28183 		 * buffer may be the same, or from different slices.
28184 		 */
28185 		duk_memmove_unsafe((void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg) + target_ustart),
28186 		                   (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + source_ustart),
28187 		                   (size_t) copy_size);
28188 	} else {
28189 		DUK_DDD(DUK_DDDPRINT("buffer copy not covered by underlying buffer(s), ignoring"));
28190 	}
28191 
28192  silent_ignore:
28193 	/* Return value is like write(), number of bytes written.
28194 	 * The return value matters because of code like:
28195 	 * "off += buf.copy(...)".
28196          */
28197 	duk_push_uint(thr, copy_size);
28198 	return 1;
28199 
28200  fail_bounds:
28201 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28202 }
28203 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28204 
28205 /*
28206  *  TypedArray.prototype.set()
28207  *
28208  *  TypedArray set() is pretty interesting to implement because:
28209  *
28210  *    - The source argument may be a plain array or a typedarray.  If the
28211  *      source is a TypedArray, values are decoded and re-encoded into the
28212  *      target (not as a plain byte copy).  This may happen even when the
28213  *      element byte size is the same, e.g. integer values may be re-encoded
28214  *      into floats.
28215  *
28216  *    - Source and target may refer to the same underlying buffer, so that
28217  *      the set() operation may overlap.  The specification requires that this
28218  *      must work as if a copy was made before the operation.  Note that this
28219  *      is NOT a simple memmove() situation because the source and target
28220  *      byte sizes may be different -- e.g. a 4-byte source (Int8Array) may
28221  *      expand to a 16-byte target (Uint32Array) so that the target overlaps
28222  *      the source both from beginning and the end (unlike in typical memmove).
28223  *
28224  *    - Even if 'buf' pointers of the source and target differ, there's no
28225  *      guarantee that their memory areas don't overlap.  This may be the
28226  *      case with external buffers.
28227  *
28228  *  Even so, it is nice to optimize for the common case:
28229  *
28230  *    - Source and target separate buffers or non-overlapping.
28231  *
28232  *    - Source and target have a compatible type so that a plain byte copy
28233  *      is possible.  Note that while e.g. uint8 and int8 are compatible
28234  *      (coercion one way or another doesn't change the byte representation),
28235  *      e.g. int8 and uint8clamped are NOT compatible when writing int8
28236  *      values into uint8clamped typedarray (-1 would clamp to 0 for instance).
28237  *
28238  *  See test-bi-typedarray-proto-set.js.
28239  */
28240 
28241 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_typedarray_set(duk_hthread * thr)28242 DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_hthread *thr) {
28243 	duk_hbufobj *h_this;
28244 	duk_hobject *h_obj;
28245 	duk_uarridx_t i, n;
28246 	duk_int_t offset_signed;
28247 	duk_uint_t offset_elems;
28248 	duk_uint_t offset_bytes;
28249 
28250 	h_this = duk__require_bufobj_this(thr);
28251 	DUK_ASSERT(h_this != NULL);
28252 	DUK_ASSERT_HBUFOBJ_VALID(h_this);
28253 
28254 	if (h_this->buf == NULL) {
28255 		DUK_DDD(DUK_DDDPRINT("source neutered, skip copy"));
28256 		return 0;
28257 	}
28258 
28259 	duk_hbufobj_promote_plain(thr, 0);
28260 	h_obj = duk_require_hobject(thr, 0);
28261 
28262 	/* XXX: V8 throws a TypeError for negative values.  Would it
28263 	 * be more useful to interpret negative offsets here from the
28264 	 * end of the buffer too?
28265 	 */
28266 	offset_signed = duk_to_int(thr, 1);
28267 	if (offset_signed < 0) {
28268 		/* For some reason this is a TypeError (at least in V8). */
28269 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28270 	}
28271 	offset_elems = (duk_uint_t) offset_signed;
28272 	offset_bytes = offset_elems << h_this->shift;
28273 	if ((offset_bytes >> h_this->shift) != offset_elems) {
28274 		/* Byte length would overflow. */
28275 		/* XXX: easier check with less code? */
28276 		goto fail_args;
28277 	}
28278 	if (offset_bytes > h_this->length) {
28279 		/* Equality may be OK but >length not.  Checking
28280 		 * this explicitly avoids some overflow cases
28281 		 * below.
28282 		 */
28283 		goto fail_args;
28284 	}
28285 	DUK_ASSERT(offset_bytes <= h_this->length);
28286 
28287 	/* Fast path: source is a TypedArray (or any bufobj). */
28288 
28289 	if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
28290 		duk_hbufobj *h_bufarg;
28291 #if !defined(DUK_USE_PREFER_SIZE)
28292 		duk_uint16_t comp_mask;
28293 #endif
28294 		duk_small_int_t no_overlap = 0;
28295 		duk_uint_t src_length;
28296 		duk_uint_t dst_length;
28297 		duk_uint_t dst_length_elems;
28298 		duk_uint8_t *p_src_base;
28299 		duk_uint8_t *p_src_end;
28300 		duk_uint8_t *p_src;
28301 		duk_uint8_t *p_dst_base;
28302 		duk_uint8_t *p_dst;
28303 		duk_small_uint_t src_elem_size;
28304 		duk_small_uint_t dst_elem_size;
28305 
28306 		h_bufarg = (duk_hbufobj *) h_obj;
28307 		DUK_ASSERT_HBUFOBJ_VALID(h_bufarg);
28308 
28309 		if (h_bufarg->buf == NULL) {
28310 			DUK_DDD(DUK_DDDPRINT("target neutered, skip copy"));
28311 			return 0;
28312 		}
28313 
28314 		/* Nominal size check. */
28315 		src_length = h_bufarg->length;  /* bytes in source */
28316 		dst_length_elems = (src_length >> h_bufarg->shift);  /* elems in source and dest */
28317 		dst_length = dst_length_elems << h_this->shift;  /* bytes in dest */
28318 		if ((dst_length >> h_this->shift) != dst_length_elems) {
28319 			/* Byte length would overflow. */
28320 			/* XXX: easier check with less code? */
28321 			goto fail_args;
28322 		}
28323 		DUK_DDD(DUK_DDDPRINT("nominal size check: src_length=%ld, dst_length=%ld",
28324 		                     (long) src_length, (long) dst_length));
28325 		DUK_ASSERT(offset_bytes <= h_this->length);
28326 		if (dst_length > h_this->length - offset_bytes) {
28327 			/* Overflow not an issue because subtraction is used on the right
28328 			 * side and guaranteed to be >= 0.
28329 			 */
28330 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28331 			goto fail_args;
28332 		}
28333 		if (!DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_this, offset_bytes + dst_length)) {
28334 			DUK_DDD(DUK_DDDPRINT("copy not covered by underlying target buffer, ignore"));
28335 			return 0;
28336 		}
28337 
28338 		p_src_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufarg);
28339 		p_dst_base = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + offset_bytes;
28340 
28341 		/* Check actual underlying buffers for validity and that they
28342 		 * cover the copy.  No side effects are allowed after the check
28343 		 * so that the validity status doesn't change.
28344 		 */
28345 		if (!DUK_HBUFOBJ_VALID_SLICE(h_this) ||
28346 		    !DUK_HBUFOBJ_VALID_SLICE(h_bufarg)) {
28347 			/* The condition could be more narrow and check for the
28348 			 * copy area only, but there's no need for fine grained
28349 			 * behavior when the underlying buffer is misconfigured.
28350 			 */
28351 			DUK_DDD(DUK_DDDPRINT("source and/or target not covered by underlying buffer, skip copy"));
28352 			return 0;
28353 		}
28354 
28355 		/* We want to do a straight memory copy if possible: this is
28356 		 * an important operation because .set() is the TypedArray
28357 		 * way to copy chunks of memory.  However, because set()
28358 		 * conceptually works in terms of elements, not all views are
28359 		 * compatible with direct byte copying.
28360 		 *
28361 		 * If we do manage a direct copy, the "overlap issue" handled
28362 		 * below can just be solved using memmove() because the source
28363 		 * and destination element sizes are necessarily equal.
28364 		 */
28365 
28366 #if !defined(DUK_USE_PREFER_SIZE)
28367 		DUK_ASSERT(h_this->elem_type < sizeof(duk__buffer_elemtype_copy_compatible) / sizeof(duk_uint16_t));
28368 		comp_mask = duk__buffer_elemtype_copy_compatible[h_this->elem_type];
28369 		if (comp_mask & (1 << h_bufarg->elem_type)) {
28370 			DUK_ASSERT(src_length == dst_length);
28371 
28372 			DUK_DDD(DUK_DDDPRINT("fast path: able to use memmove() because views are compatible"));
28373 			duk_memmove_unsafe((void *) p_dst_base, (const void *) p_src_base, (size_t) dst_length);
28374 			return 0;
28375 		}
28376 		DUK_DDD(DUK_DDDPRINT("fast path: views are not compatible with a byte copy, copy by item"));
28377 #endif  /* !DUK_USE_PREFER_SIZE */
28378 
28379 		/* We want to avoid making a copy to process set() but that's
28380 		 * not always possible: the source and the target may overlap
28381 		 * and because element sizes are different, the overlap cannot
28382 		 * always be handled with a memmove() or choosing the copy
28383 		 * direction in a certain way.  For example, if source type is
28384 		 * uint8 and target type is uint32, the target area may exceed
28385 		 * the source area from both ends!
28386 		 *
28387 		 * Note that because external buffers may point to the same
28388 		 * memory areas, we must ultimately make this check using
28389 		 * pointers.
28390 		 *
28391 		 * NOTE: careful with side effects: any side effect may cause
28392 		 * a buffer resize (or external buffer pointer/length update)!
28393 		 */
28394 
28395 		DUK_DDD(DUK_DDDPRINT("overlap check: p_src_base=%p, src_length=%ld, "
28396 		                     "p_dst_base=%p, dst_length=%ld",
28397 		                     (void *) p_src_base, (long) src_length,
28398 		                     (void *) p_dst_base, (long) dst_length));
28399 
28400 		if (p_src_base >= p_dst_base + dst_length ||  /* source starts after dest ends */
28401 		    p_src_base + src_length <= p_dst_base) {   /* source ends before dest starts */
28402 			no_overlap = 1;
28403 		}
28404 
28405 		if (!no_overlap) {
28406 			/* There's overlap: the desired end result is that
28407 			 * conceptually a copy is made to avoid "trampling"
28408 			 * of source data by destination writes.  We make
28409 			 * an actual temporary copy to handle this case.
28410 			 */
28411 			duk_uint8_t *p_src_copy;
28412 
28413 			DUK_DDD(DUK_DDDPRINT("there is overlap, make a copy of the source"));
28414 			p_src_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_length);
28415 			DUK_ASSERT(p_src_copy != NULL);
28416 			duk_memcpy_unsafe((void *) p_src_copy, (const void *) p_src_base, (size_t) src_length);
28417 
28418 			p_src_base = p_src_copy;  /* use p_src_base from now on */
28419 		}
28420 		/* Value stack intentionally mixed size here. */
28421 
28422 		DUK_DDD(DUK_DDDPRINT("after overlap check: p_src_base=%p, src_length=%ld, "
28423 		                     "p_dst_base=%p, dst_length=%ld, valstack top=%ld",
28424 		                     (void *) p_src_base, (long) src_length,
28425 		                     (void *) p_dst_base, (long) dst_length,
28426 		                     (long) duk_get_top(thr)));
28427 
28428 		/* Ready to make the copy.  We must proceed element by element
28429 		 * and must avoid any side effects that might cause the buffer
28430 		 * validity check above to become invalid.
28431 		 *
28432 		 * Although we work through the value stack here, only plain
28433 		 * numbers are handled which should be side effect safe.
28434 		 */
28435 
28436 		src_elem_size = (duk_small_uint_t) (1U << h_bufarg->shift);
28437 		dst_elem_size = (duk_small_uint_t) (1U << h_this->shift);
28438 		p_src = p_src_base;
28439 		p_dst = p_dst_base;
28440 		p_src_end = p_src_base + src_length;
28441 
28442 		while (p_src != p_src_end) {
28443 			DUK_DDD(DUK_DDDPRINT("fast path per element copy loop: "
28444 			                     "p_src=%p, p_src_end=%p, p_dst=%p",
28445 			                     (void *) p_src, (void *) p_src_end, (void *) p_dst));
28446 			/* A validated read() is always a number, so it's write coercion
28447 			 * is always side effect free an won't invalidate pointers etc.
28448 			 */
28449 			duk_hbufobj_push_validated_read(thr, h_bufarg, p_src, src_elem_size);
28450 			duk_hbufobj_validated_write(thr, h_this, p_dst, dst_elem_size);
28451 			duk_pop(thr);
28452 			p_src += src_elem_size;
28453 			p_dst += dst_elem_size;
28454 		}
28455 
28456 		return 0;
28457 	} else {
28458 		/* Slow path: quite slow, but we save space by using the property code
28459 		 * to write coerce target values.  We don't need to worry about overlap
28460 		 * here because the source is not a TypedArray.
28461 		 *
28462 		 * We could use the bufobj write coercion helper but since the
28463 		 * property read may have arbitrary side effects, full validity checks
28464 		 * would be needed for every element anyway.
28465 		 */
28466 
28467 		n = (duk_uarridx_t) duk_get_length(thr, 0);
28468 		DUK_ASSERT(offset_bytes <= h_this->length);
28469 		if ((n << h_this->shift) > h_this->length - offset_bytes) {
28470 			/* Overflow not an issue because subtraction is used on the right
28471 			 * side and guaranteed to be >= 0.
28472 			 */
28473 			DUK_DDD(DUK_DDDPRINT("copy exceeds target buffer nominal length"));
28474 			goto fail_args;
28475 		}
28476 
28477 		/* There's no need to check for buffer validity status for the
28478 		 * target here: the property access code will do that for each
28479 		 * element.  Moreover, if we did check the validity here, side
28480 		 * effects from reading the source argument might invalidate
28481 		 * the results anyway.
28482 		 */
28483 
28484 		DUK_ASSERT_TOP(thr, 2);
28485 		duk_push_this(thr);
28486 
28487 		for (i = 0; i < n; i++) {
28488 			duk_get_prop_index(thr, 0, i);
28489 			duk_put_prop_index(thr, 2, offset_elems + i);
28490 		}
28491 	}
28492 
28493 	return 0;
28494 
28495  fail_args:
28496 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28497 }
28498 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28499 
28500 /*
28501  *  Node.js Buffer.prototype.slice([start], [end])
28502  *  ArrayBuffer.prototype.slice(begin, [end])
28503  *  TypedArray.prototype.subarray(begin, [end])
28504  *
28505  *  The API calls are almost identical; negative indices are counted from end
28506  *  of buffer, and final indices are clamped (allowing crossed indices).  Main
28507  *  differences:
28508  *
28509  *    - Copy/view behavior; Node.js .slice() and TypedArray .subarray() create
28510  *      views, ArrayBuffer .slice() creates a copy
28511  *
28512  *    - Resulting object has a different class and prototype depending on the
28513  *      call (or 'this' argument)
28514  *
28515  *    - TypedArray .subarray() arguments are element indices, not byte offsets
28516  *
28517  *    - Plain buffer argument creates a plain buffer slice
28518  */
28519 
28520 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__arraybuffer_plain_slice(duk_hthread * thr,duk_hbuffer * h_val)28521 DUK_LOCAL void duk__arraybuffer_plain_slice(duk_hthread *thr, duk_hbuffer *h_val) {
28522 	duk_int_t start_offset, end_offset;
28523 	duk_uint_t slice_length;
28524 	duk_uint8_t *p_copy;
28525 	duk_size_t copy_length;
28526 
28527 	duk__clamp_startend_negidx_shifted(thr,
28528 	                                   (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val),
28529 	                                   0 /*buffer_shift*/,
28530 	                                   0 /*idx_start*/,
28531 	                                   1 /*idx_end*/,
28532 	                                   &start_offset,
28533 	                                   &end_offset);
28534 	DUK_ASSERT(end_offset <= (duk_int_t) DUK_HBUFFER_GET_SIZE(h_val));
28535 	DUK_ASSERT(start_offset >= 0);
28536 	DUK_ASSERT(end_offset >= start_offset);
28537 	slice_length = (duk_uint_t) (end_offset - start_offset);
28538 
28539 	p_copy = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, (duk_size_t) slice_length);
28540 	DUK_ASSERT(p_copy != NULL);
28541 	copy_length = slice_length;
28542 
28543 	duk_memcpy_unsafe((void *) p_copy,
28544 	                  (const void *) ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_val) + start_offset),
28545 	                  copy_length);
28546 }
28547 #endif /* DUK_USE_BUFFEROBJECT_SUPPORT */
28548 
28549 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28550 /* Shared helper for slice/subarray operation.
28551  * Magic: 0x01=isView, 0x02=copy, 0x04=Node.js Buffer special handling.
28552  */
duk_bi_buffer_slice_shared(duk_hthread * thr)28553 DUK_INTERNAL duk_ret_t duk_bi_buffer_slice_shared(duk_hthread *thr) {
28554 	duk_small_int_t magic;
28555 	duk_small_uint_t res_class_num;
28556 	duk_small_int_t res_proto_bidx;
28557 	duk_hbufobj *h_this;
28558 	duk_hbufobj *h_bufobj;
28559 	duk_hbuffer *h_val;
28560 	duk_int_t start_offset, end_offset;
28561 	duk_uint_t slice_length;
28562 	duk_tval *tv;
28563 
28564 	/* [ start end ] */
28565 
28566 	magic = duk_get_current_magic(thr);
28567 
28568 	tv = duk_get_borrowed_this_tval(thr);
28569 	DUK_ASSERT(tv != NULL);
28570 
28571 	if (DUK_TVAL_IS_BUFFER(tv)) {
28572 		/* For plain buffers return a plain buffer slice. */
28573 		h_val = DUK_TVAL_GET_BUFFER(tv);
28574 		DUK_ASSERT(h_val != NULL);
28575 
28576 		if (magic & 0x02) {
28577 			/* Make copy: ArrayBuffer.prototype.slice() uses this. */
28578 			duk__arraybuffer_plain_slice(thr, h_val);
28579 			return 1;
28580 		} else {
28581 			/* View into existing buffer: cannot be done if the
28582 			 * result is a plain buffer because there's no slice
28583 			 * info.  So return an ArrayBuffer instance; coerce
28584 			 * the 'this' binding into an object and behave as if
28585 			 * the original call was for an Object-coerced plain
28586 			 * buffer (handled automatically by duk__require_bufobj_this()).
28587 			 */
28588 
28589 			DUK_DDD(DUK_DDDPRINT("slice() doesn't handle view into plain buffer, coerce 'this' to ArrayBuffer object"));
28590 			/* fall through */
28591 		}
28592 	}
28593 	tv = NULL;  /* No longer valid nor needed. */
28594 
28595 	h_this = duk__require_bufobj_this(thr);
28596 
28597 	/* Slice offsets are element (not byte) offsets, which only matters
28598 	 * for TypedArray views, Node.js Buffer and ArrayBuffer have shift
28599 	 * zero so byte and element offsets are the same.  Negative indices
28600 	 * are counted from end of slice, crossed indices are allowed (and
28601 	 * result in zero length result), and final values are clamped
28602 	 * against the current slice.  There's intentionally no check
28603 	 * against the underlying buffer here.
28604 	 */
28605 
28606 	duk__clamp_startend_negidx_shifted(thr,
28607 	                                   (duk_int_t) h_this->length,
28608 	                                   (duk_uint8_t) h_this->shift,
28609 	                                   0 /*idx_start*/,
28610 	                                   1 /*idx_end*/,
28611 	                                   &start_offset,
28612 	                                   &end_offset);
28613 	DUK_ASSERT(end_offset >= start_offset);
28614 	DUK_ASSERT(start_offset >= 0);
28615 	DUK_ASSERT(end_offset >= 0);
28616 	slice_length = (duk_uint_t) (end_offset - start_offset);
28617 
28618 	/* The resulting buffer object gets the same class and prototype as
28619 	 * the buffer in 'this', e.g. if the input is a Uint8Array the
28620 	 * result is a Uint8Array; if the input is a Float32Array, the
28621 	 * result is a Float32Array.  The result internal prototype should
28622 	 * be the default prototype for the class (e.g. initial value of
28623 	 * Uint8Array.prototype), not copied from the argument (Duktape 1.x
28624 	 * did that).
28625 	 *
28626 	 * Node.js Buffers have special handling: they're Uint8Arrays as far
28627 	 * as the internal class is concerned, so the new Buffer should also
28628 	 * be an Uint8Array but inherit from Buffer.prototype.
28629 	 */
28630 	res_class_num = DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_this);
28631 	DUK_ASSERT(res_class_num >= DUK_HOBJECT_CLASS_BUFOBJ_MIN);  /* type check guarantees */
28632 	DUK_ASSERT(res_class_num <= DUK_HOBJECT_CLASS_BUFOBJ_MAX);
28633 	res_proto_bidx = duk__buffer_proto_from_classnum[res_class_num - DUK_HOBJECT_CLASS_BUFOBJ_MIN];
28634 	if (magic & 0x04) {
28635 		res_proto_bidx = DUK_BIDX_NODEJS_BUFFER_PROTOTYPE;
28636 	}
28637 	h_bufobj = duk_push_bufobj_raw(thr,
28638 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28639 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28640 	                               DUK_HOBJECT_CLASS_AS_FLAGS(res_class_num),
28641 	                               res_proto_bidx);
28642 	DUK_ASSERT(h_bufobj != NULL);
28643 
28644 	DUK_ASSERT(h_bufobj->length == 0);
28645 	h_bufobj->shift = h_this->shift;  /* inherit */
28646 	h_bufobj->elem_type = h_this->elem_type;  /* inherit */
28647 	h_bufobj->is_typedarray = magic & 0x01;
28648 	DUK_ASSERT(h_bufobj->is_typedarray == 0 || h_bufobj->is_typedarray == 1);
28649 
28650 	h_val = h_this->buf;
28651 	if (h_val == NULL) {
28652 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28653 	}
28654 
28655 	if (magic & 0x02) {
28656 		/* non-zero: make copy */
28657 		duk_uint8_t *p_copy;
28658 		duk_size_t copy_length;
28659 
28660 		p_copy = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, (duk_size_t) slice_length);  /* must be zeroed, not all bytes always copied */
28661 		DUK_ASSERT(p_copy != NULL);
28662 
28663 		/* Copy slice, respecting underlying buffer limits; remainder
28664 		 * is left as zero.
28665 		 */
28666 		copy_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, slice_length);
28667 		duk_memcpy_unsafe((void *) p_copy,
28668 		                  (const void *) (DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this) + start_offset),
28669 		                  copy_length);
28670 
28671 		h_val = duk_known_hbuffer(thr, -1);
28672 
28673 		h_bufobj->buf = h_val;
28674 		DUK_HBUFFER_INCREF(thr, h_val);
28675 		h_bufobj->length = slice_length;
28676 		DUK_ASSERT(h_bufobj->offset == 0);
28677 
28678 		duk_pop(thr);  /* reachable so pop OK */
28679 	} else {
28680 		h_bufobj->buf = h_val;
28681 		DUK_HBUFFER_INCREF(thr, h_val);
28682 		h_bufobj->length = slice_length;
28683 		h_bufobj->offset = h_this->offset + (duk_uint_t) start_offset;
28684 
28685 		/* Copy the .buffer property, needed for TypedArray.prototype.subarray().
28686 		 *
28687 		 * XXX: limit copy only for TypedArray classes specifically?
28688 		 */
28689 
28690 		DUK_ASSERT(h_bufobj->buf_prop == NULL);
28691 		h_bufobj->buf_prop = h_this->buf_prop;  /* may be NULL */
28692 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, (duk_hobject *) h_bufobj->buf_prop);
28693 	}
28694 	/* unbalanced stack on purpose */
28695 
28696 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
28697 	return 1;
28698 }
28699 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28700 
28701 /*
28702  *  Node.js Buffer.isEncoding()
28703  */
28704 
28705 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_encoding(duk_hthread * thr)28706 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_encoding(duk_hthread *thr) {
28707 	const char *encoding;
28708 
28709 	/* only accept lowercase 'utf8' now. */
28710 
28711 	encoding = duk_to_string(thr, 0);
28712 	DUK_ASSERT(duk_is_string(thr, 0));  /* guaranteed by duk_to_string() */
28713 	duk_push_boolean(thr, DUK_STRCMP(encoding, "utf8") == 0);
28714 	return 1;
28715 }
28716 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28717 
28718 /*
28719  *  Node.js Buffer.isBuffer()
28720  */
28721 
28722 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_is_buffer(duk_hthread * thr)28723 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_is_buffer(duk_hthread *thr) {
28724 	duk_hobject *h;
28725 	duk_hobject *h_proto;
28726 	duk_bool_t ret = 0;
28727 
28728 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* nargs */
28729 	h = duk_get_hobject(thr, 0);
28730 	if (h != NULL) {
28731 		h_proto = thr->builtins[DUK_BIDX_NODEJS_BUFFER_PROTOTYPE];
28732 		DUK_ASSERT(h_proto != NULL);
28733 
28734 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
28735 		if (h != NULL) {
28736 			ret = duk_hobject_prototype_chain_contains(thr, h, h_proto, 0 /*ignore_loop*/);
28737 		}
28738 	}
28739 
28740 	duk_push_boolean(thr, ret);
28741 	return 1;
28742 }
28743 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28744 
28745 /*
28746  *  Node.js Buffer.byteLength()
28747  */
28748 
28749 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_byte_length(duk_hthread * thr)28750 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_byte_length(duk_hthread *thr) {
28751 	const char *str;
28752 	duk_size_t len;
28753 
28754 	/* At the moment Buffer(<str>) will just use the string bytes as
28755 	 * is (ignoring encoding), so we return the string length here
28756 	 * unconditionally.
28757 	 */
28758 
28759 	/* XXX: to be revised; Old Node.js behavior just coerces any buffer
28760 	 * values to string:
28761 	 * $ node
28762 	 * > Buffer.byteLength(new Uint32Array(10))
28763 	 * 20
28764 	 * > Buffer.byteLength(new Uint32Array(100))
28765 	 * 20
28766 	 * (The 20 comes from '[object Uint32Array]'.length
28767 	 */
28768 
28769 	str = duk_to_lstring(thr, 0, &len);
28770 	DUK_UNREF(str);
28771 	duk_push_size_t(thr, len);
28772 	return 1;
28773 }
28774 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28775 
28776 /*
28777  *  Node.js Buffer.concat()
28778  */
28779 
28780 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_bi_nodejs_buffer_concat(duk_hthread * thr)28781 DUK_INTERNAL duk_ret_t duk_bi_nodejs_buffer_concat(duk_hthread *thr) {
28782 	duk_hobject *h_arg;
28783 	duk_uint_t total_length;
28784 	duk_hbufobj *h_bufobj;
28785 	duk_hbufobj *h_bufres;
28786 	duk_hbuffer *h_val;
28787 	duk_uint_t i, n;
28788 	duk_uint8_t *p;
28789 	duk_size_t space_left;
28790 	duk_size_t copy_size;
28791 
28792 	/* Node.js accepts only actual Arrays. */
28793 	h_arg = duk_require_hobject(thr, 0);
28794 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h_arg) != DUK_HOBJECT_CLASS_ARRAY) {
28795 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
28796 	}
28797 
28798 	/* Compute result length and validate argument buffers. */
28799 	n = (duk_uint_t) duk_get_length(thr, 0);
28800 	total_length = 0;
28801 	for (i = 0; i < n; i++) {
28802 		/* Neutered checks not necessary here: neutered buffers have
28803 		 * zero 'length' so we'll effectively skip them.
28804 		 */
28805 		DUK_ASSERT_TOP(thr, 2);  /* [ array totalLength ] */
28806 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);  /* -> [ array totalLength buf ] */
28807 		h_bufobj = duk__require_bufobj_value(thr, 2);
28808 		DUK_ASSERT(h_bufobj != NULL);
28809 		total_length += h_bufobj->length;
28810 		if (DUK_UNLIKELY(total_length < h_bufobj->length)) {
28811 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);  /* Wrapped. */
28812 		}
28813 		duk_pop(thr);
28814 	}
28815 	/* In Node.js v0.12.1 a 1-element array is special and won't create a
28816 	 * copy, this was fixed later so an explicit check no longer needed.
28817 	 */
28818 
28819 	/* User totalLength overrides a computed length, but we'll check
28820 	 * every copy in the copy loop.  Note that duk_to_int() can
28821 	 * technically have arbitrary side effects so we need to recheck
28822 	 * the buffers in the copy loop.
28823 	 */
28824 	if (!duk_is_undefined(thr, 1) && n > 0) {
28825 		/* For n == 0, Node.js ignores totalLength argument and
28826 		 * returns a zero length buffer.
28827 		 */
28828 		duk_int_t total_length_signed;
28829 		total_length_signed = duk_to_int(thr, 1);
28830 		if (total_length_signed < 0) {
28831 			DUK_DCERROR_RANGE_INVALID_ARGS(thr);
28832 		}
28833 		total_length = (duk_uint_t) total_length_signed;
28834 	}
28835 
28836 	h_bufres = duk_push_bufobj_raw(thr,
28837 	                               DUK_HOBJECT_FLAG_EXTENSIBLE |
28838 	                               DUK_HOBJECT_FLAG_BUFOBJ |
28839 	                               DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_UINT8ARRAY),
28840 	                               DUK_BIDX_NODEJS_BUFFER_PROTOTYPE);
28841 	DUK_ASSERT(h_bufres != NULL);
28842 
28843 	p = (duk_uint8_t *) duk_push_fixed_buffer_zero(thr, total_length);  /* must be zeroed, all bytes not necessarily written over */
28844 	DUK_ASSERT(p != NULL);
28845 	space_left = (duk_size_t) total_length;
28846 
28847 	for (i = 0; i < n; i++) {
28848 		DUK_ASSERT_TOP(thr, 4);  /* [ array totalLength bufres buf ] */
28849 
28850 		duk_get_prop_index(thr, 0, (duk_uarridx_t) i);
28851 		h_bufobj = duk__require_bufobj_value(thr, 4);
28852 		DUK_ASSERT(h_bufobj != NULL);
28853 
28854 		copy_size = h_bufobj->length;
28855 		if (copy_size > space_left) {
28856 			copy_size = space_left;
28857 		}
28858 
28859 		if (h_bufobj->buf != NULL &&
28860 		    DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
28861 			duk_memcpy_unsafe((void *) p,
28862 			                  (const void *) DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_bufobj),
28863 			                  copy_size);
28864 		} else {
28865 			/* Just skip, leaving zeroes in the result. */
28866 			;
28867 		}
28868 		p += copy_size;
28869 		space_left -= copy_size;
28870 
28871 		duk_pop(thr);
28872 	}
28873 
28874 	h_val = duk_known_hbuffer(thr, -1);
28875 
28876 	duk__set_bufobj_buffer(thr, h_bufres, h_val);
28877 	h_bufres->is_typedarray = 1;
28878 	DUK_ASSERT_HBUFOBJ_VALID(h_bufres);
28879 
28880 	duk_pop(thr);  /* pop plain buffer, now reachable through h_bufres */
28881 
28882 	return 1;  /* return h_bufres */
28883 }
28884 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
28885 
28886 /*
28887  *  Shared readfield and writefield methods
28888  *
28889  *  The readfield/writefield methods need support for endianness and field
28890  *  types.  All offsets are byte based so no offset shifting is needed.
28891  */
28892 
28893 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
28894 /* Format of magic, bits:
28895  *   0...1: field type; 0=uint8, 1=uint16, 2=uint32, 3=float, 4=double, 5=unused, 6=unused, 7=unused
28896  *       3: endianness: 0=little, 1=big
28897  *       4: signed: 1=yes, 0=no
28898  *       5: typedarray: 1=yes, 0=no
28899  */
28900 #define  DUK__FLD_8BIT         0
28901 #define  DUK__FLD_16BIT        1
28902 #define  DUK__FLD_32BIT        2
28903 #define  DUK__FLD_FLOAT        3
28904 #define  DUK__FLD_DOUBLE       4
28905 #define  DUK__FLD_VARINT       5
28906 #define  DUK__FLD_BIGENDIAN    (1 << 3)
28907 #define  DUK__FLD_SIGNED       (1 << 4)
28908 #define  DUK__FLD_TYPEDARRAY   (1 << 5)
28909 
28910 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_readfield(duk_hthread * thr)28911 DUK_INTERNAL duk_ret_t duk_bi_buffer_readfield(duk_hthread *thr) {
28912 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
28913 	duk_small_int_t magic_ftype;
28914 	duk_small_int_t magic_bigendian;
28915 	duk_small_int_t magic_signed;
28916 	duk_small_int_t magic_typedarray;
28917 	duk_small_int_t endswap;
28918 	duk_hbufobj *h_this;
28919 	duk_bool_t no_assert;
28920 	duk_int_t offset_signed;
28921 	duk_uint_t offset;
28922 	duk_uint_t buffer_length;
28923 	duk_uint_t check_length;
28924 	duk_uint8_t *buf;
28925 	duk_double_union du;
28926 
28927 	magic_ftype = magic & 0x0007;
28928 	magic_bigendian = magic & 0x0008;
28929 	magic_signed = magic & 0x0010;
28930 	magic_typedarray = magic & 0x0020;
28931 
28932 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
28933 	DUK_ASSERT(h_this != NULL);
28934 	buffer_length = h_this->length;
28935 
28936 	/* [ offset noAssert                 ], when ftype != DUK__FLD_VARINT */
28937 	/* [ offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
28938 	/* [ offset littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
28939 
28940 	/* Handle TypedArray vs. Node.js Buffer arg differences */
28941 	if (magic_typedarray) {
28942 		no_assert = 0;
28943 #if defined(DUK_USE_INTEGER_LE)
28944 		endswap = !duk_to_boolean(thr, 1);  /* 1=little endian */
28945 #else
28946 		endswap = duk_to_boolean(thr, 1);  /* 1=little endian */
28947 #endif
28948 	} else {
28949 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 2 : 1);
28950 #if defined(DUK_USE_INTEGER_LE)
28951 		endswap = magic_bigendian;
28952 #else
28953 		endswap = !magic_bigendian;
28954 #endif
28955 	}
28956 
28957 	/* Offset is coerced first to signed integer range and then to unsigned.
28958 	 * This ensures we can add a small byte length (1-8) to the offset in
28959 	 * bound checks and not wrap.
28960 	 */
28961 	offset_signed = duk_to_int(thr, 0);
28962 	offset = (duk_uint_t) offset_signed;
28963 	if (offset_signed < 0) {
28964 		goto fail_bounds;
28965 	}
28966 
28967 	DUK_DDD(DUK_DDDPRINT("readfield, buffer_length=%ld, offset=%ld, no_assert=%d, "
28968 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
28969 	                     "endswap=%d",
28970 	                     (long) buffer_length, (long) offset, (int) no_assert,
28971 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
28972 	                     (int) (magic_signed >> 4), (int) endswap));
28973 
28974 	/* Update 'buffer_length' to be the effective, safe limit which
28975 	 * takes into account the underlying buffer.  This value will be
28976 	 * potentially invalidated by any side effect.
28977 	 */
28978 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
28979 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
28980 	                     (long) buffer_length, (long) check_length));
28981 
28982 	if (h_this->buf) {
28983 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
28984 	} else {
28985 		/* Neutered.  We could go into the switch-case safely with
28986 		 * buf == NULL because check_length == 0.  To avoid scanbuild
28987 		 * warnings, fail directly instead.
28988 		 */
28989 		DUK_ASSERT(check_length == 0);
28990 		goto fail_neutered;
28991 	}
28992 	DUK_ASSERT(buf != NULL);
28993 
28994 	switch (magic_ftype) {
28995 	case DUK__FLD_8BIT: {
28996 		duk_uint8_t tmp;
28997 		if (offset + 1U > check_length) {
28998 			goto fail_bounds;
28999 		}
29000 		tmp = buf[offset];
29001 		if (magic_signed) {
29002 			duk_push_int(thr, (duk_int_t) ((duk_int8_t) tmp));
29003 		} else {
29004 			duk_push_uint(thr, (duk_uint_t) tmp);
29005 		}
29006 		break;
29007 	}
29008 	case DUK__FLD_16BIT: {
29009 		duk_uint16_t tmp;
29010 		if (offset + 2U > check_length) {
29011 			goto fail_bounds;
29012 		}
29013 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 2);
29014 		tmp = du.us[0];
29015 		if (endswap) {
29016 			tmp = DUK_BSWAP16(tmp);
29017 		}
29018 		if (magic_signed) {
29019 			duk_push_int(thr, (duk_int_t) ((duk_int16_t) tmp));
29020 		} else {
29021 			duk_push_uint(thr, (duk_uint_t) tmp);
29022 		}
29023 		break;
29024 	}
29025 	case DUK__FLD_32BIT: {
29026 		duk_uint32_t tmp;
29027 		if (offset + 4U > check_length) {
29028 			goto fail_bounds;
29029 		}
29030 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29031 		tmp = du.ui[0];
29032 		if (endswap) {
29033 			tmp = DUK_BSWAP32(tmp);
29034 		}
29035 		if (magic_signed) {
29036 			duk_push_int(thr, (duk_int_t) ((duk_int32_t) tmp));
29037 		} else {
29038 			duk_push_uint(thr, (duk_uint_t) tmp);
29039 		}
29040 		break;
29041 	}
29042 	case DUK__FLD_FLOAT: {
29043 		duk_uint32_t tmp;
29044 		if (offset + 4U > check_length) {
29045 			goto fail_bounds;
29046 		}
29047 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 4);
29048 		if (endswap) {
29049 			tmp = du.ui[0];
29050 			tmp = DUK_BSWAP32(tmp);
29051 			du.ui[0] = tmp;
29052 		}
29053 		duk_push_number(thr, (duk_double_t) du.f[0]);
29054 		break;
29055 	}
29056 	case DUK__FLD_DOUBLE: {
29057 		if (offset + 8U > check_length) {
29058 			goto fail_bounds;
29059 		}
29060 		duk_memcpy((void *) du.uc, (const void *) (buf + offset), 8);
29061 		if (endswap) {
29062 			DUK_DBLUNION_BSWAP64(&du);
29063 		}
29064 		duk_push_number(thr, (duk_double_t) du.d);
29065 		break;
29066 	}
29067 	case DUK__FLD_VARINT: {
29068 		/* Node.js Buffer variable width integer field.  We don't really
29069 		 * care about speed here, so aim for shortest algorithm.
29070 		 */
29071 		duk_int_t field_bytelen;
29072 		duk_int_t i, i_step, i_end;
29073 #if defined(DUK_USE_64BIT_OPS)
29074 		duk_int64_t tmp;
29075 		duk_small_uint_t shift_tmp;
29076 #else
29077 		duk_double_t tmp;
29078 		duk_small_int_t highbyte;
29079 #endif
29080 		const duk_uint8_t *p;
29081 
29082 		field_bytelen = duk_get_int(thr, 1);  /* avoid side effects! */
29083 		if (field_bytelen < 1 || field_bytelen > 6) {
29084 			goto fail_field_length;
29085 		}
29086 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29087 			goto fail_bounds;
29088 		}
29089 		p = (const duk_uint8_t *) (buf + offset);
29090 
29091 		/* Slow gathering of value using either 64-bit arithmetic
29092 		 * or IEEE doubles if 64-bit types not available.  Handling
29093 		 * of negative numbers is a bit non-obvious in both cases.
29094 		 */
29095 
29096 		if (magic_bigendian) {
29097 			/* Gather in big endian */
29098 			i = 0;
29099 			i_step = 1;
29100 			i_end = field_bytelen;  /* one i_step over */
29101 		} else {
29102 			/* Gather in little endian */
29103 			i = field_bytelen - 1;
29104 			i_step = -1;
29105 			i_end = -1;  /* one i_step over */
29106 		}
29107 
29108 #if defined(DUK_USE_64BIT_OPS)
29109 		tmp = 0;
29110 		do {
29111 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29112 			tmp = (tmp << 8) + (duk_int64_t) p[i];
29113 			i += i_step;
29114 		} while (i != i_end);
29115 
29116 		if (magic_signed) {
29117 			/* Shift to sign extend.  Left shift must be unsigned
29118 			 * to avoid undefined behavior; right shift must be
29119 			 * signed to sign extend properly.
29120 			 */
29121 			shift_tmp = (duk_small_uint_t) (64U - (duk_small_uint_t) field_bytelen * 8U);
29122 			tmp = (duk_int64_t) ((duk_uint64_t) tmp << shift_tmp) >> shift_tmp;
29123 		}
29124 
29125 		duk_push_i64(thr, tmp);
29126 #else
29127 		highbyte = p[i];
29128 		if (magic_signed && (highbyte & 0x80) != 0) {
29129 			/* 0xff => 255 - 256 = -1; 0x80 => 128 - 256 = -128 */
29130 			tmp = (duk_double_t) (highbyte - 256);
29131 		} else {
29132 			tmp = (duk_double_t) highbyte;
29133 		}
29134 		for (;;) {
29135 			i += i_step;
29136 			if (i == i_end) {
29137 				break;
29138 			}
29139 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29140 			tmp = (tmp * 256.0) + (duk_double_t) p[i];
29141 		}
29142 
29143 		duk_push_number(thr, tmp);
29144 #endif
29145 		break;
29146 	}
29147 	default: {  /* should never happen but default here */
29148 		goto fail_bounds;
29149 	}
29150 	}
29151 
29152 	return 1;
29153 
29154  fail_neutered:
29155  fail_field_length:
29156  fail_bounds:
29157 	if (no_assert) {
29158 		/* Node.js return value for noAssert out-of-bounds reads is
29159 		 * usually (but not always) NaN.  Return NaN consistently.
29160 		 */
29161 		duk_push_nan(thr);
29162 		return 1;
29163 	}
29164 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29165 }
29166 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29167 
29168 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
29169 /* XXX: split into separate functions for each field type? */
duk_bi_buffer_writefield(duk_hthread * thr)29170 DUK_INTERNAL duk_ret_t duk_bi_buffer_writefield(duk_hthread *thr) {
29171 	duk_small_int_t magic = (duk_small_int_t) duk_get_current_magic(thr);
29172 	duk_small_int_t magic_ftype;
29173 	duk_small_int_t magic_bigendian;
29174 	duk_small_int_t magic_signed;
29175 	duk_small_int_t magic_typedarray;
29176 	duk_small_int_t endswap;
29177 	duk_hbufobj *h_this;
29178 	duk_bool_t no_assert;
29179 	duk_int_t offset_signed;
29180 	duk_uint_t offset;
29181 	duk_uint_t buffer_length;
29182 	duk_uint_t check_length;
29183 	duk_uint8_t *buf;
29184 	duk_double_union du;
29185 	duk_int_t nbytes = 0;
29186 
29187 	magic_ftype = magic & 0x0007;
29188 	magic_bigendian = magic & 0x0008;
29189 	magic_signed = magic & 0x0010;
29190 	magic_typedarray = magic & 0x0020;
29191 	DUK_UNREF(magic_signed);
29192 
29193 	h_this = duk__require_bufobj_this(thr);  /* XXX: very inefficient for plain buffers */
29194 	DUK_ASSERT(h_this != NULL);
29195 	buffer_length = h_this->length;
29196 
29197 	/* [ value  offset noAssert                 ], when ftype != DUK__FLD_VARINT */
29198 	/* [ value  offset fieldByteLength noAssert ], when ftype == DUK__FLD_VARINT */
29199 	/* [ offset value  littleEndian             ], when DUK__FLD_TYPEDARRAY (regardless of ftype) */
29200 
29201 	/* Handle TypedArray vs. Node.js Buffer arg differences */
29202 	if (magic_typedarray) {
29203 		no_assert = 0;
29204 #if defined(DUK_USE_INTEGER_LE)
29205 		endswap = !duk_to_boolean(thr, 2);  /* 1=little endian */
29206 #else
29207 		endswap = duk_to_boolean(thr, 2);  /* 1=little endian */
29208 #endif
29209 		duk_swap(thr, 0, 1);  /* offset/value order different from Node.js */
29210 	} else {
29211 		no_assert = duk_to_boolean(thr, (magic_ftype == DUK__FLD_VARINT) ? 3 : 2);
29212 #if defined(DUK_USE_INTEGER_LE)
29213 		endswap = magic_bigendian;
29214 #else
29215 		endswap = !magic_bigendian;
29216 #endif
29217 	}
29218 
29219 	/* Offset is coerced first to signed integer range and then to unsigned.
29220 	 * This ensures we can add a small byte length (1-8) to the offset in
29221 	 * bound checks and not wrap.
29222 	 */
29223 	offset_signed = duk_to_int(thr, 1);
29224 	offset = (duk_uint_t) offset_signed;
29225 
29226 	/* We need 'nbytes' even for a failed offset; return value must be
29227 	 * (offset + nbytes) even when write fails due to invalid offset.
29228 	 */
29229 	if (magic_ftype != DUK__FLD_VARINT) {
29230 		DUK_ASSERT(magic_ftype >= 0 && magic_ftype < (duk_small_int_t) (sizeof(duk__buffer_nbytes_from_fldtype) / sizeof(duk_uint8_t)));
29231 		nbytes = duk__buffer_nbytes_from_fldtype[magic_ftype];
29232 	} else {
29233 		nbytes = duk_get_int(thr, 2);
29234 		if (nbytes < 1 || nbytes > 6) {
29235 			goto fail_field_length;
29236 		}
29237 	}
29238 	DUK_ASSERT(nbytes >= 1 && nbytes <= 8);
29239 
29240 	/* Now we can check offset validity. */
29241 	if (offset_signed < 0) {
29242 		goto fail_bounds;
29243 	}
29244 
29245 	DUK_DDD(DUK_DDDPRINT("writefield, value=%!T, buffer_length=%ld, offset=%ld, no_assert=%d, "
29246 	                     "magic=%04x, magic_fieldtype=%d, magic_bigendian=%d, magic_signed=%d, "
29247 	                     "endswap=%d",
29248 	                     duk_get_tval(thr, 0), (long) buffer_length, (long) offset, (int) no_assert,
29249 	                     (unsigned int) magic, (int) magic_ftype, (int) (magic_bigendian >> 3),
29250 	                     (int) (magic_signed >> 4), (int) endswap));
29251 
29252 	/* Coerce value to a number before computing check_length, so that
29253 	 * the field type specific coercion below can't have side effects
29254 	 * that would invalidate check_length.
29255 	 */
29256 	duk_to_number(thr, 0);
29257 
29258 	/* Update 'buffer_length' to be the effective, safe limit which
29259 	 * takes into account the underlying buffer.  This value will be
29260 	 * potentially invalidated by any side effect.
29261 	 */
29262 	check_length = DUK_HBUFOBJ_CLAMP_BYTELENGTH(h_this, buffer_length);
29263 	DUK_DDD(DUK_DDDPRINT("buffer_length=%ld, check_length=%ld",
29264 	                     (long) buffer_length, (long) check_length));
29265 
29266 	if (h_this->buf) {
29267 		buf = DUK_HBUFOBJ_GET_SLICE_BASE(thr->heap, h_this);
29268 	} else {
29269 		/* Neutered.  We could go into the switch-case safely with
29270 		 * buf == NULL because check_length == 0.  To avoid scanbuild
29271 		 * warnings, fail directly instead.
29272 		 */
29273 		DUK_ASSERT(check_length == 0);
29274 		goto fail_neutered;
29275 	}
29276 	DUK_ASSERT(buf != NULL);
29277 
29278 	switch (magic_ftype) {
29279 	case DUK__FLD_8BIT: {
29280 		if (offset + 1U > check_length) {
29281 			goto fail_bounds;
29282 		}
29283 		/* sign doesn't matter when writing */
29284 		buf[offset] = (duk_uint8_t) duk_to_uint32(thr, 0);
29285 		break;
29286 	}
29287 	case DUK__FLD_16BIT: {
29288 		duk_uint16_t tmp;
29289 		if (offset + 2U > check_length) {
29290 			goto fail_bounds;
29291 		}
29292 		tmp = (duk_uint16_t) duk_to_uint32(thr, 0);
29293 		if (endswap) {
29294 			tmp = DUK_BSWAP16(tmp);
29295 		}
29296 		du.us[0] = tmp;
29297 		/* sign doesn't matter when writing */
29298 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 2);
29299 		break;
29300 	}
29301 	case DUK__FLD_32BIT: {
29302 		duk_uint32_t tmp;
29303 		if (offset + 4U > check_length) {
29304 			goto fail_bounds;
29305 		}
29306 		tmp = (duk_uint32_t) duk_to_uint32(thr, 0);
29307 		if (endswap) {
29308 			tmp = DUK_BSWAP32(tmp);
29309 		}
29310 		du.ui[0] = tmp;
29311 		/* sign doesn't matter when writing */
29312 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29313 		break;
29314 	}
29315 	case DUK__FLD_FLOAT: {
29316 		duk_uint32_t tmp;
29317 		if (offset + 4U > check_length) {
29318 			goto fail_bounds;
29319 		}
29320 		du.f[0] = (duk_float_t) duk_to_number(thr, 0);
29321 		if (endswap) {
29322 			tmp = du.ui[0];
29323 			tmp = DUK_BSWAP32(tmp);
29324 			du.ui[0] = tmp;
29325 		}
29326 		/* sign doesn't matter when writing */
29327 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 4);
29328 		break;
29329 	}
29330 	case DUK__FLD_DOUBLE: {
29331 		if (offset + 8U > check_length) {
29332 			goto fail_bounds;
29333 		}
29334 		du.d = (duk_double_t) duk_to_number(thr, 0);
29335 		if (endswap) {
29336 			DUK_DBLUNION_BSWAP64(&du);
29337 		}
29338 		/* sign doesn't matter when writing */
29339 		duk_memcpy((void *) (buf + offset), (const void *) du.uc, 8);
29340 		break;
29341 	}
29342 	case DUK__FLD_VARINT: {
29343 		/* Node.js Buffer variable width integer field.  We don't really
29344 		 * care about speed here, so aim for shortest algorithm.
29345 		 */
29346 		duk_int_t field_bytelen;
29347 		duk_int_t i, i_step, i_end;
29348 #if defined(DUK_USE_64BIT_OPS)
29349 		duk_int64_t tmp;
29350 #else
29351 		duk_double_t tmp;
29352 #endif
29353 		duk_uint8_t *p;
29354 
29355 		field_bytelen = (duk_int_t) nbytes;
29356 		if (offset + (duk_uint_t) field_bytelen > check_length) {
29357 			goto fail_bounds;
29358 		}
29359 
29360 		/* Slow writing of value using either 64-bit arithmetic
29361 		 * or IEEE doubles if 64-bit types not available.  There's
29362 		 * no special sign handling when writing varints.
29363 		 */
29364 
29365 		if (magic_bigendian) {
29366 			/* Write in big endian */
29367 			i = field_bytelen;  /* one i_step added at top of loop */
29368 			i_step = -1;
29369 			i_end = 0;
29370 		} else {
29371 			/* Write in little endian */
29372 			i = -1;  /* one i_step added at top of loop */
29373 			i_step = 1;
29374 			i_end = field_bytelen - 1;
29375 		}
29376 
29377 		/* XXX: The duk_to_number() cast followed by integer coercion
29378 		 * is platform specific so NaN, +/- Infinity, and out-of-bounds
29379 		 * values result in platform specific output now.
29380 		 * See: test-bi-nodejs-buffer-proto-varint-special.js
29381 		 */
29382 
29383 #if defined(DUK_USE_64BIT_OPS)
29384 		tmp = (duk_int64_t) duk_to_number(thr, 0);
29385 		p = (duk_uint8_t *) (buf + offset);
29386 		do {
29387 			i += i_step;
29388 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29389 			p[i] = (duk_uint8_t) (tmp & 0xff);
29390 			tmp = tmp >> 8;  /* unnecessary shift for last byte */
29391 		} while (i != i_end);
29392 #else
29393 		tmp = duk_to_number(thr, 0);
29394 		p = (duk_uint8_t *) (buf + offset);
29395 		do {
29396 			i += i_step;
29397 			tmp = DUK_FLOOR(tmp);
29398 			DUK_ASSERT(i >= 0 && i < field_bytelen);
29399 			p[i] = (duk_uint8_t) (DUK_FMOD(tmp, 256.0));
29400 			tmp = tmp / 256.0;  /* unnecessary div for last byte */
29401 		} while (i != i_end);
29402 #endif
29403 		break;
29404 	}
29405 	default: {  /* should never happen but default here */
29406 		goto fail_bounds;
29407 	}
29408 	}
29409 
29410 	/* Node.js Buffer: return offset + #bytes written (i.e. next
29411 	 * write offset).
29412 	 */
29413 	if (magic_typedarray) {
29414 		/* For TypedArrays 'undefined' return value is specified
29415 		 * by ES2015 (matches V8).
29416 		 */
29417 		return 0;
29418 	}
29419 	duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29420 	return 1;
29421 
29422  fail_neutered:
29423  fail_field_length:
29424  fail_bounds:
29425 	if (no_assert) {
29426 		/* Node.js return value for failed writes is offset + #bytes
29427 		 * that would have been written.
29428 		 */
29429 		/* XXX: for negative input offsets, 'offset' will be a large
29430 		 * positive value so the result here is confusing.
29431 		 */
29432 		if (magic_typedarray) {
29433 			return 0;
29434 		}
29435 		duk_push_uint(thr, offset + (duk_uint_t) nbytes);
29436 		return 1;
29437 	}
29438 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
29439 }
29440 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29441 
29442 /*
29443  *  Accessors for .buffer, .byteLength, .byteOffset
29444  */
29445 
29446 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk__autospawn_arraybuffer(duk_hthread * thr,duk_hbuffer * h_buf)29447 DUK_LOCAL duk_hbufobj *duk__autospawn_arraybuffer(duk_hthread *thr, duk_hbuffer *h_buf) {
29448 	duk_hbufobj *h_res;
29449 
29450 	h_res = duk_push_bufobj_raw(thr,
29451 	                            DUK_HOBJECT_FLAG_EXTENSIBLE |
29452 	                            DUK_HOBJECT_FLAG_BUFOBJ |
29453 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARRAYBUFFER),
29454 	                            DUK_BIDX_ARRAYBUFFER_PROTOTYPE);
29455 	DUK_ASSERT(h_res != NULL);
29456 	DUK_UNREF(h_res);
29457 
29458 	duk__set_bufobj_buffer(thr, h_res, h_buf);
29459 	DUK_ASSERT_HBUFOBJ_VALID(h_res);
29460 	DUK_ASSERT(h_res->buf_prop == NULL);
29461 	return h_res;
29462 }
29463 
duk_bi_typedarray_buffer_getter(duk_hthread * thr)29464 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29465 	duk_hbufobj *h_bufobj;
29466 
29467 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29468 	DUK_ASSERT(h_bufobj != NULL);
29469 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29470 		DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for plain buffer"));
29471 		(void) duk__autospawn_arraybuffer(thr, (duk_hbuffer *) h_bufobj);
29472 		return 1;
29473 	} else {
29474 		if (h_bufobj->buf_prop == NULL &&
29475 		    DUK_HOBJECT_GET_CLASS_NUMBER((duk_hobject *) h_bufobj) != DUK_HOBJECT_CLASS_ARRAYBUFFER &&
29476 		    h_bufobj->buf != NULL) {
29477 			duk_hbufobj *h_arrbuf;
29478 
29479 			DUK_DD(DUK_DDPRINT("autospawn ArrayBuffer for typed array or DataView"));
29480 			h_arrbuf = duk__autospawn_arraybuffer(thr, h_bufobj->buf);
29481 
29482 			if (h_bufobj->buf_prop == NULL) {
29483 				/* Must recheck buf_prop, in case ArrayBuffer
29484 				 * alloc had a side effect which already filled
29485 				 * it!
29486 				 */
29487 
29488 				/* Set ArrayBuffer's .byteOffset and .byteLength based
29489 				 * on the view so that Arraybuffer[view.byteOffset]
29490 				 * matches view[0].
29491 				 */
29492 				h_arrbuf->offset = 0;
29493 				DUK_ASSERT(h_bufobj->offset + h_bufobj->length >= h_bufobj->offset);  /* Wrap check on creation. */
29494 				h_arrbuf->length = h_bufobj->offset + h_bufobj->length;
29495 				DUK_ASSERT(h_arrbuf->buf_prop == NULL);
29496 
29497 				DUK_ASSERT(h_bufobj->buf_prop == NULL);
29498 				h_bufobj->buf_prop = (duk_hobject *) h_arrbuf;
29499 				DUK_HBUFOBJ_INCREF(thr, h_arrbuf);  /* Now reachable and accounted for. */
29500 			}
29501 
29502 			/* Left on stack; pushed for the second time below (OK). */
29503 		}
29504 		if (h_bufobj->buf_prop) {
29505 			duk_push_hobject(thr, h_bufobj->buf_prop);
29506 			return 1;
29507 		}
29508 	}
29509 	return 0;
29510 }
29511 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29512 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29513 	duk_hbufobj *h_bufobj;
29514 
29515 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29516 	DUK_ASSERT(h_bufobj != NULL);
29517 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29518 		duk_push_uint(thr, 0);
29519 	} else {
29520 		/* If neutered must return 0; offset is zeroed during
29521 		 * neutering.
29522 		 */
29523 		duk_push_uint(thr, h_bufobj->offset);
29524 	}
29525 	return 1;
29526 }
29527 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29528 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29529 	duk_hbufobj *h_bufobj;
29530 
29531 	h_bufobj = (duk_hbufobj *) duk__getrequire_bufobj_this(thr, DUK__BUFOBJ_FLAG_THROW /*flags*/);
29532 	DUK_ASSERT(h_bufobj != NULL);
29533 	if (DUK_HEAPHDR_IS_BUFFER((duk_heaphdr *) h_bufobj)) {
29534 		duk_hbuffer *h_buf;
29535 
29536 		h_buf = (duk_hbuffer *) h_bufobj;
29537 		DUK_ASSERT(DUK_HBUFFER_GET_SIZE(h_buf) <= DUK_UINT_MAX);  /* Buffer limits. */
29538 		duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
29539 	} else {
29540 		/* If neutered must return 0; length is zeroed during
29541 		 * neutering.
29542 		 */
29543 		duk_push_uint(thr, h_bufobj->length);
29544 	}
29545 	return 1;
29546 }
29547 #else  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29548 /* No .buffer getter without ArrayBuffer support. */
29549 #if 0
29550 DUK_INTERNAL duk_ret_t duk_bi_typedarray_buffer_getter(duk_hthread *thr) {
29551 	return 0;
29552 }
29553 #endif
29554 
duk_bi_typedarray_byteoffset_getter(duk_hthread * thr)29555 DUK_INTERNAL duk_ret_t duk_bi_typedarray_byteoffset_getter(duk_hthread *thr) {
29556 	duk_push_uint(thr, 0);
29557 	return 1;
29558 }
29559 
duk_bi_typedarray_bytelength_getter(duk_hthread * thr)29560 DUK_INTERNAL duk_ret_t duk_bi_typedarray_bytelength_getter(duk_hthread *thr) {
29561 	duk_hbuffer *h_buf;
29562 
29563 	/* XXX: helper? */
29564 	duk_push_this(thr);
29565 	h_buf = duk_require_hbuffer(thr, -1);
29566 	duk_push_uint(thr, DUK_HBUFFER_GET_SIZE(h_buf));
29567 	return 1;
29568 }
29569 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
29570 
29571 /* automatic undefs */
29572 #undef DUK__BUFOBJ_FLAG_PROMOTE
29573 #undef DUK__BUFOBJ_FLAG_THROW
29574 #undef DUK__FLD_16BIT
29575 #undef DUK__FLD_32BIT
29576 #undef DUK__FLD_8BIT
29577 #undef DUK__FLD_BIGENDIAN
29578 #undef DUK__FLD_DOUBLE
29579 #undef DUK__FLD_FLOAT
29580 #undef DUK__FLD_SIGNED
29581 #undef DUK__FLD_TYPEDARRAY
29582 #undef DUK__FLD_VARINT
29583 #line 1 "duk_bi_date.c"
29584 /*
29585  *  Date built-ins
29586  *
29587  *  Unlike most built-ins, Date has some platform dependencies for getting
29588  *  UTC time, converting between UTC and local time, and parsing and
29589  *  formatting time values.  These are all abstracted behind DUK_USE_xxx
29590  *  config options.  There are built-in platform specific providers for
29591  *  POSIX and Windows, but external providers can also be used.
29592  *
29593  *  See doc/datetime.rst.
29594  *
29595  */
29596 
29597 /* #include duk_internal.h -> already included */
29598 
29599 /* XXX: currently defines unnecessary symbols when DUK_USE_DATE_BUILTIN is disabled. */
29600 
29601 /*
29602  *  Forward declarations
29603  */
29604 
29605 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);
29606 DUK_LOCAL_DECL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags);
29607 DUK_LOCAL_DECL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val);
29608 DUK_LOCAL_DECL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags);
29609 
29610 /*
29611  *  Other file level defines
29612  */
29613 
29614 /* Debug macro to print all parts and dparts (used manually because of debug level). */
29615 #define  DUK__DPRINT_PARTS_AND_DPARTS(parts,dparts)  do { \
29616 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld, dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29617 		                 (long) (parts)[0], (long) (parts)[1], \
29618 		                 (long) (parts)[2], (long) (parts)[3], \
29619 		                 (long) (parts)[4], (long) (parts)[5], \
29620 		                 (long) (parts)[6], (long) (parts)[7], \
29621 		                 (double) (dparts)[0], (double) (dparts)[1], \
29622 		                 (double) (dparts)[2], (double) (dparts)[3], \
29623 		                 (double) (dparts)[4], (double) (dparts)[5], \
29624 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29625 	} while (0)
29626 #define  DUK__DPRINT_PARTS(parts)  do { \
29627 		DUK_D(DUK_DPRINT("parts: %ld %ld %ld %ld %ld %ld %ld %ld", \
29628 		                 (long) (parts)[0], (long) (parts)[1], \
29629 		                 (long) (parts)[2], (long) (parts)[3], \
29630 		                 (long) (parts)[4], (long) (parts)[5], \
29631 		                 (long) (parts)[6], (long) (parts)[7])); \
29632 	} while (0)
29633 #define  DUK__DPRINT_DPARTS(dparts)  do { \
29634 		DUK_D(DUK_DPRINT("dparts: %lf %lf %lf %lf %lf %lf %lf %lf", \
29635 		                 (double) (dparts)[0], (double) (dparts)[1], \
29636 		                 (double) (dparts)[2], (double) (dparts)[3], \
29637 		                 (double) (dparts)[4], (double) (dparts)[5], \
29638 		                 (double) (dparts)[6], (double) (dparts)[7])); \
29639 	} while (0)
29640 
29641 /* Equivalent year for DST calculations outside [1970,2038[ range, see
29642  * E5 Section 15.9.1.8.  Equivalent year has the same leap-year-ness and
29643  * starts with the same weekday on Jan 1.
29644  * https://bugzilla.mozilla.org/show_bug.cgi?id=351066
29645  */
29646 #define DUK__YEAR(x) ((duk_uint8_t) ((x) - 1970))
29647 DUK_LOCAL duk_uint8_t duk__date_equivyear[14] = {
29648 #if 1
29649 	/* This is based on V8 EquivalentYear() algorithm (see util/genequivyear.py):
29650 	 * http://code.google.com/p/v8/source/browse/trunk/src/date.h#146
29651 	 */
29652 
29653 	/* non-leap year: sunday, monday, ... */
29654 	DUK__YEAR(2023), DUK__YEAR(2035), DUK__YEAR(2019), DUK__YEAR(2031),
29655 	DUK__YEAR(2015), DUK__YEAR(2027), DUK__YEAR(2011),
29656 
29657 	/* leap year: sunday, monday, ... */
29658 	DUK__YEAR(2012), DUK__YEAR(2024), DUK__YEAR(2008), DUK__YEAR(2020),
29659 	DUK__YEAR(2032), DUK__YEAR(2016), DUK__YEAR(2028)
29660 #endif
29661 
29662 #if 0
29663 	/* This is based on Rhino EquivalentYear() algorithm:
29664 	 * https://github.com/mozilla/rhino/blob/f99cc11d616f0cdda2c42bde72b3484df6182947/src/org/mozilla/javascript/NativeDate.java
29665 	 */
29666 
29667 	/* non-leap year: sunday, monday, ... */
29668 	DUK__YEAR(1978), DUK__YEAR(1973), DUK__YEAR(1985), DUK__YEAR(1986),
29669 	DUK__YEAR(1981), DUK__YEAR(1971), DUK__YEAR(1977),
29670 
29671 	/* leap year: sunday, monday, ... */
29672 	DUK__YEAR(1984), DUK__YEAR(1996), DUK__YEAR(1980), DUK__YEAR(1992),
29673 	DUK__YEAR(1976), DUK__YEAR(1988), DUK__YEAR(1972)
29674 #endif
29675 };
29676 
29677 /*
29678  *  ISO 8601 subset parser.
29679  */
29680 
29681 /* Parser part count. */
29682 #define DUK__NUM_ISO8601_PARSER_PARTS  9
29683 
29684 /* Parser part indices. */
29685 #define DUK__PI_YEAR         0
29686 #define DUK__PI_MONTH        1
29687 #define DUK__PI_DAY          2
29688 #define DUK__PI_HOUR         3
29689 #define DUK__PI_MINUTE       4
29690 #define DUK__PI_SECOND       5
29691 #define DUK__PI_MILLISECOND  6
29692 #define DUK__PI_TZHOUR       7
29693 #define DUK__PI_TZMINUTE     8
29694 
29695 /* Parser part masks. */
29696 #define DUK__PM_YEAR         (1 << DUK__PI_YEAR)
29697 #define DUK__PM_MONTH        (1 << DUK__PI_MONTH)
29698 #define DUK__PM_DAY          (1 << DUK__PI_DAY)
29699 #define DUK__PM_HOUR         (1 << DUK__PI_HOUR)
29700 #define DUK__PM_MINUTE       (1 << DUK__PI_MINUTE)
29701 #define DUK__PM_SECOND       (1 << DUK__PI_SECOND)
29702 #define DUK__PM_MILLISECOND  (1 << DUK__PI_MILLISECOND)
29703 #define DUK__PM_TZHOUR       (1 << DUK__PI_TZHOUR)
29704 #define DUK__PM_TZMINUTE     (1 << DUK__PI_TZMINUTE)
29705 
29706 /* Parser separator indices. */
29707 #define DUK__SI_PLUS         0
29708 #define DUK__SI_MINUS        1
29709 #define DUK__SI_T            2
29710 #define DUK__SI_SPACE        3
29711 #define DUK__SI_COLON        4
29712 #define DUK__SI_PERIOD       5
29713 #define DUK__SI_Z            6
29714 #define DUK__SI_NUL          7
29715 
29716 /* Parser separator masks. */
29717 #define DUK__SM_PLUS         (1 << DUK__SI_PLUS)
29718 #define DUK__SM_MINUS        (1 << DUK__SI_MINUS)
29719 #define DUK__SM_T            (1 << DUK__SI_T)
29720 #define DUK__SM_SPACE        (1 << DUK__SI_SPACE)
29721 #define DUK__SM_COLON        (1 << DUK__SI_COLON)
29722 #define DUK__SM_PERIOD       (1 << DUK__SI_PERIOD)
29723 #define DUK__SM_Z            (1 << DUK__SI_Z)
29724 #define DUK__SM_NUL          (1 << DUK__SI_NUL)
29725 
29726 /* Rule control flags. */
29727 #define DUK__CF_NEG          (1 << 0)  /* continue matching, set neg_tzoffset flag */
29728 #define DUK__CF_ACCEPT       (1 << 1)  /* accept string */
29729 #define DUK__CF_ACCEPT_NUL   (1 << 2)  /* accept string if next char is NUL (otherwise reject) */
29730 
29731 #define DUK__PACK_RULE(partmask,sepmask,nextpart,flags)  \
29732 	((duk_uint32_t) (partmask) + \
29733 	 (((duk_uint32_t) (sepmask)) << 9) + \
29734 	 (((duk_uint32_t) (nextpart)) << 17) + \
29735 	 (((duk_uint32_t) (flags)) << 21))
29736 
29737 #define DUK__UNPACK_RULE(rule,var_nextidx,var_flags)  do { \
29738 		(var_nextidx) = (duk_small_uint_t) (((rule) >> 17) & 0x0f); \
29739 		(var_flags) = (duk_small_uint_t) ((rule) >> 21); \
29740 	} while (0)
29741 
29742 #define DUK__RULE_MASK_PART_SEP  0x1ffffUL
29743 
29744 /* Matching separator index is used in the control table */
29745 DUK_LOCAL const duk_uint8_t duk__parse_iso8601_seps[] = {
29746 	DUK_ASC_PLUS /*0*/, DUK_ASC_MINUS /*1*/, DUK_ASC_UC_T /*2*/, DUK_ASC_SPACE /*3*/,
29747 	DUK_ASC_COLON /*4*/, DUK_ASC_PERIOD /*5*/, DUK_ASC_UC_Z /*6*/, DUK_ASC_NUL /*7*/
29748 };
29749 
29750 /* Rule table: first matching rule is used to determine what to do next. */
29751 DUK_LOCAL const duk_uint32_t duk__parse_iso8601_control[] = {
29752 	DUK__PACK_RULE(DUK__PM_YEAR, DUK__SM_MINUS, DUK__PI_MONTH, 0),
29753 	DUK__PACK_RULE(DUK__PM_MONTH, DUK__SM_MINUS, DUK__PI_DAY, 0),
29754 	DUK__PACK_RULE(DUK__PM_YEAR | DUK__PM_MONTH | DUK__PM_DAY, DUK__SM_T | DUK__SM_SPACE, DUK__PI_HOUR, 0),
29755 	DUK__PACK_RULE(DUK__PM_HOUR, DUK__SM_COLON, DUK__PI_MINUTE, 0),
29756 	DUK__PACK_RULE(DUK__PM_MINUTE, DUK__SM_COLON, DUK__PI_SECOND, 0),
29757 	DUK__PACK_RULE(DUK__PM_SECOND, DUK__SM_PERIOD, DUK__PI_MILLISECOND, 0),
29758 	DUK__PACK_RULE(DUK__PM_TZHOUR, DUK__SM_COLON, DUK__PI_TZMINUTE, 0),
29759 	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),
29760 	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),
29761 	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),
29762 	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)
29763 
29764 	/* Note1: the specification doesn't require matching a time form with
29765 	 *        just hours ("HH"), but we accept it here, e.g. "2012-01-02T12Z".
29766 	 *
29767 	 * Note2: the specification doesn't require matching a timezone offset
29768 	 *        with just hours ("HH"), but accept it here, e.g. "2012-01-02T03:04:05+02"
29769 	 */
29770 };
29771 
duk__parse_string_iso8601_subset(duk_hthread * thr,const char * str)29772 DUK_LOCAL duk_bool_t duk__parse_string_iso8601_subset(duk_hthread *thr, const char *str) {
29773 	duk_int_t parts[DUK__NUM_ISO8601_PARSER_PARTS];
29774 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
29775 	duk_double_t d;
29776 	const duk_uint8_t *p;
29777 	duk_small_uint_t part_idx = 0;
29778 	duk_int_t accum = 0;
29779 	duk_small_uint_t ndigits = 0;
29780 	duk_bool_t neg_year = 0;
29781 	duk_bool_t neg_tzoffset = 0;
29782 	duk_uint_fast8_t ch;
29783 	duk_small_uint_t i;
29784 
29785 	/* During parsing, month and day are one-based; set defaults here. */
29786 	duk_memzero(parts, sizeof(parts));
29787 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] == 0);  /* don't care value, year is mandatory */
29788 	parts[DUK_DATE_IDX_MONTH] = 1;
29789 	parts[DUK_DATE_IDX_DAY] = 1;
29790 
29791 	/* Special handling for year sign. */
29792 	p = (const duk_uint8_t *) str;
29793 	ch = p[0];
29794 	if (ch == DUK_ASC_PLUS) {
29795 		p++;
29796 	} else if (ch == DUK_ASC_MINUS) {
29797 		neg_year = 1;
29798 		p++;
29799 	}
29800 
29801 	for (;;) {
29802 		ch = *p++;
29803 		DUK_DDD(DUK_DDDPRINT("parsing, part_idx=%ld, char=%ld ('%c')",
29804 		                     (long) part_idx, (long) ch,
29805 		                     (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : DUK_ASC_QUESTION)));
29806 
29807 		if (ch >= DUK_ASC_0 && ch <= DUK_ASC_9) {
29808 			if (ndigits >= 9) {
29809 				DUK_DDD(DUK_DDDPRINT("too many digits -> reject"));
29810 				goto reject;
29811 			}
29812 			if (part_idx == DUK__PI_MILLISECOND && ndigits >= 3) {
29813 				/* ignore millisecond fractions after 3 */
29814 			} else {
29815 				accum = accum * 10 + ((duk_int_t) ch) - ((duk_int_t) DUK_ASC_0) + 0x00;
29816 				ndigits++;
29817 			}
29818 		} else {
29819 			duk_uint_fast32_t match_val;
29820 			duk_small_uint_t sep_idx;
29821 
29822 			if (ndigits <= 0) {
29823 				goto reject;
29824 			}
29825 			if (part_idx == DUK__PI_MILLISECOND) {
29826 				/* complete the millisecond field */
29827 				while (ndigits < 3) {
29828 					accum *= 10;
29829 					ndigits++;
29830 				}
29831 			}
29832 			parts[part_idx] = accum;
29833 			DUK_DDD(DUK_DDDPRINT("wrote part %ld -> value %ld", (long) part_idx, (long) accum));
29834 
29835 			accum = 0;
29836 			ndigits = 0;
29837 
29838 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t)); i++) {
29839 				if (duk__parse_iso8601_seps[i] == ch) {
29840 					break;
29841 				}
29842 			}
29843 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_seps) / sizeof(duk_uint8_t))) {
29844 				DUK_DDD(DUK_DDDPRINT("separator character doesn't match -> reject"));
29845 				goto reject;
29846 			}
29847 
29848 			sep_idx = i;
29849 			match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
29850 
29851 			for (i = 0; i < (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t)); i++) {
29852 				duk_uint_fast32_t rule = duk__parse_iso8601_control[i];
29853 				duk_small_uint_t nextpart;
29854 				duk_small_uint_t cflags;
29855 
29856 				DUK_DDD(DUK_DDDPRINT("part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, considering rule=0x%08lx",
29857 				                     (long) part_idx, (long) sep_idx,
29858 				                     (unsigned long) match_val, (unsigned long) rule));
29859 
29860 				if ((rule & match_val) != match_val) {
29861 					continue;
29862 				}
29863 
29864 				DUK__UNPACK_RULE(rule, nextpart, cflags);
29865 
29866 				DUK_DDD(DUK_DDDPRINT("rule match -> part_idx=%ld, sep_idx=%ld, match_val=0x%08lx, "
29867 				                     "rule=0x%08lx -> nextpart=%ld, cflags=0x%02lx",
29868 				                     (long) part_idx, (long) sep_idx,
29869 				                     (unsigned long) match_val, (unsigned long) rule,
29870 				                     (long) nextpart, (unsigned long) cflags));
29871 
29872 				if (cflags & DUK__CF_NEG) {
29873 					neg_tzoffset = 1;
29874 				}
29875 
29876 				if (cflags & DUK__CF_ACCEPT) {
29877 					goto accept;
29878 				}
29879 
29880 				if (cflags & DUK__CF_ACCEPT_NUL) {
29881 					DUK_ASSERT(*(p - 1) != (char) 0);
29882 					if (*p == DUK_ASC_NUL) {
29883 						goto accept;
29884 					}
29885 					goto reject;
29886 				}
29887 
29888 				part_idx = nextpart;
29889 				break;
29890 			}  /* rule match */
29891 
29892 			if (i == (duk_small_uint_t) (sizeof(duk__parse_iso8601_control) / sizeof(duk_uint32_t))) {
29893 				DUK_DDD(DUK_DDDPRINT("no rule matches -> reject"));
29894 				goto reject;
29895 			}
29896 
29897 			if (ch == 0) {
29898 				/* This shouldn't be necessary, but check just in case
29899 				 * to avoid any chance of overruns.
29900 				 */
29901 				DUK_DDD(DUK_DDDPRINT("NUL after rule matching (should not happen) -> reject"));
29902 				goto reject;
29903 			}
29904 		}  /* if-digit-else-ctrl */
29905 	}  /* char loop */
29906 
29907 	/* We should never exit the loop above. */
29908 	DUK_UNREACHABLE();
29909 
29910  reject:
29911 	DUK_DDD(DUK_DDDPRINT("reject"));
29912 	return 0;
29913 
29914  accept:
29915 	DUK_DDD(DUK_DDDPRINT("accept"));
29916 
29917 	/* Apply timezone offset to get the main parts in UTC */
29918 	if (neg_year) {
29919 		parts[DUK__PI_YEAR] = -parts[DUK__PI_YEAR];
29920 	}
29921 	if (neg_tzoffset) {
29922 		parts[DUK__PI_HOUR] += parts[DUK__PI_TZHOUR];
29923 		parts[DUK__PI_MINUTE] += parts[DUK__PI_TZMINUTE];
29924 	} else {
29925 		parts[DUK__PI_HOUR] -= parts[DUK__PI_TZHOUR];
29926 		parts[DUK__PI_MINUTE] -= parts[DUK__PI_TZMINUTE];
29927 	}
29928 	parts[DUK__PI_MONTH] -= 1;  /* zero-based month */
29929 	parts[DUK__PI_DAY] -= 1;  /* zero-based day */
29930 
29931 	/* Use double parts, they tolerate unnormalized time.
29932 	 *
29933 	 * Note: DUK_DATE_IDX_WEEKDAY is initialized with a bogus value (DUK__PI_TZHOUR)
29934 	 * on purpose.  It won't be actually used by duk_bi_date_get_timeval_from_dparts(),
29935 	 * but will make the value initialized just in case, and avoid any
29936 	 * potential for Valgrind issues.
29937 	 */
29938 	for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
29939 		DUK_DDD(DUK_DDDPRINT("part[%ld] = %ld", (long) i, (long) parts[i]));
29940 		dparts[i] = parts[i];
29941 	}
29942 
29943 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
29944 	duk_push_number(thr, d);
29945 	return 1;
29946 }
29947 
29948 /*
29949  *  Date/time parsing helper.
29950  *
29951  *  Parse a datetime string into a time value.  We must first try to parse
29952  *  the input according to the standard format in E5.1 Section 15.9.1.15.
29953  *  If that fails, we can try to parse using custom parsing, which can
29954  *  either be platform neutral (custom code) or platform specific (using
29955  *  existing platform API calls).
29956  *
29957  *  Note in particular that we must parse whatever toString(), toUTCString(),
29958  *  and toISOString() can produce; see E5.1 Section 15.9.4.2.
29959  *
29960  *  Returns 1 to allow tail calling.
29961  *
29962  *  There is much room for improvement here with respect to supporting
29963  *  alternative datetime formats.  For instance, V8 parses '2012-01-01' as
29964  *  UTC and '2012/01/01' as local time.
29965  */
29966 
duk__parse_string(duk_hthread * thr,const char * str)29967 DUK_LOCAL duk_ret_t duk__parse_string(duk_hthread *thr, const char *str) {
29968 	/* XXX: there is a small risk here: because the ISO 8601 parser is
29969 	 * very loose, it may end up parsing some datetime values which
29970 	 * would be better parsed with a platform specific parser.
29971 	 */
29972 
29973 	DUK_ASSERT(str != NULL);
29974 	DUK_DDD(DUK_DDDPRINT("parse datetime from string '%s'", (const char *) str));
29975 
29976 	if (duk__parse_string_iso8601_subset(thr, str) != 0) {
29977 		return 1;
29978 	}
29979 
29980 #if defined(DUK_USE_DATE_PARSE_STRING)
29981 	/* Contract, either:
29982 	 * - Push value on stack and return 1
29983 	 * - Don't push anything on stack and return 0
29984 	 */
29985 
29986 	if (DUK_USE_DATE_PARSE_STRING(thr, str) != 0) {
29987 		return 1;
29988 	}
29989 #else
29990 	/* No platform-specific parsing, this is not an error. */
29991 #endif
29992 
29993 	duk_push_nan(thr);
29994 	return 1;
29995 }
29996 
29997 /*
29998  *  Calendar helpers
29999  *
30000  *  Some helpers are used for getters and can operate on normalized values
30001  *  which can be represented with 32-bit signed integers.  Other helpers are
30002  *  needed by setters and operate on un-normalized double values, must watch
30003  *  out for non-finite numbers etc.
30004  */
30005 
30006 DUK_LOCAL duk_uint8_t duk__days_in_month[12] = {
30007 	(duk_uint8_t) 31, (duk_uint8_t) 28, (duk_uint8_t) 31, (duk_uint8_t) 30,
30008 	(duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 31,
30009 	(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
30010 };
30011 
30012 /* Maximum iteration count for computing UTC-to-local time offset when
30013  * creating an ECMAScript time value from local parts.
30014  */
30015 #define DUK__LOCAL_TZOFFSET_MAXITER   4
30016 
30017 /* Because 'day since epoch' can be negative and is used to compute weekday
30018  * using a modulo operation, add this multiple of 7 to avoid negative values
30019  * when year is below 1970 epoch.  ECMAScript time values are restricted to
30020  * +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
30021  * Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
30022  */
30023 #define DUK__WEEKDAY_MOD_ADDER  (20000000 * 7)  /* 0x08583b00 */
30024 
duk_bi_date_is_leap_year(duk_int_t year)30025 DUK_INTERNAL duk_bool_t duk_bi_date_is_leap_year(duk_int_t year) {
30026 	if ((year % 4) != 0) {
30027 		return 0;
30028 	}
30029 	if ((year % 100) != 0) {
30030 		return 1;
30031 	}
30032 	if ((year % 400) != 0) {
30033 		return 0;
30034 	}
30035 	return 1;
30036 }
30037 
duk_bi_date_timeval_in_valid_range(duk_double_t x)30038 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_valid_range(duk_double_t x) {
30039 	return (x >= -DUK_DATE_MSEC_100M_DAYS && x <= DUK_DATE_MSEC_100M_DAYS);
30040 }
30041 
duk_bi_date_timeval_in_leeway_range(duk_double_t x)30042 DUK_INTERNAL duk_bool_t duk_bi_date_timeval_in_leeway_range(duk_double_t x) {
30043 	return (x >= -DUK_DATE_MSEC_100M_DAYS_LEEWAY && x <= DUK_DATE_MSEC_100M_DAYS_LEEWAY);
30044 }
30045 
duk_bi_date_year_in_valid_range(duk_double_t x)30046 DUK_INTERNAL duk_bool_t duk_bi_date_year_in_valid_range(duk_double_t x) {
30047 	return (x >= DUK_DATE_MIN_ECMA_YEAR && x <= DUK_DATE_MAX_ECMA_YEAR);
30048 }
30049 
duk__timeclip(duk_double_t x)30050 DUK_LOCAL duk_double_t duk__timeclip(duk_double_t x) {
30051 	if (!DUK_ISFINITE(x)) {
30052 		return DUK_DOUBLE_NAN;
30053 	}
30054 
30055 	if (!duk_bi_date_timeval_in_valid_range(x)) {
30056 		return DUK_DOUBLE_NAN;
30057 	}
30058 
30059 	x = duk_js_tointeger_number(x);
30060 
30061 	/* Here we'd have the option to normalize -0 to +0. */
30062 	return x;
30063 }
30064 
30065 /* Integer division which floors also negative values correctly. */
duk__div_floor(duk_int_t a,duk_int_t b)30066 DUK_LOCAL duk_int_t duk__div_floor(duk_int_t a, duk_int_t b) {
30067 	DUK_ASSERT(b > 0);
30068 	if (a >= 0) {
30069 		return a / b;
30070 	} else {
30071 		/* e.g. a = -4, b = 5  -->  -4 - 5 + 1 / 5  -->  -8 / 5  -->  -1
30072 		 *      a = -5, b = 5  -->  -5 - 5 + 1 / 5  -->  -9 / 5  -->  -1
30073 		 *      a = -6, b = 5  -->  -6 - 5 + 1 / 5  -->  -10 / 5  -->  -2
30074 		 */
30075 		return (a - b + 1) / b;
30076 	}
30077 }
30078 
30079 /* Compute day number of the first day of a given year. */
duk__day_from_year(duk_int_t year)30080 DUK_LOCAL duk_int_t duk__day_from_year(duk_int_t year) {
30081 	/* Note: in integer arithmetic, (x / 4) is same as floor(x / 4) for non-negative
30082 	 * values, but is incorrect for negative ones.
30083 	 */
30084 	return 365 * (year - 1970)
30085 	       + duk__div_floor(year - 1969, 4)
30086 	       - duk__div_floor(year - 1901, 100)
30087 	       + duk__div_floor(year - 1601, 400);
30088 }
30089 
30090 /* 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)30091 DUK_LOCAL duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_within_year) {
30092 	duk_int_t year;
30093 	duk_int_t diff_days;
30094 
30095 	/* estimate year upwards (towards positive infinity), then back down;
30096 	 * two iterations should be enough
30097 	 */
30098 
30099 	if (day >= 0) {
30100 		year = 1970 + day / 365;
30101 	} else {
30102 		year = 1970 + day / 366;
30103 	}
30104 
30105 	for (;;) {
30106 		diff_days = duk__day_from_year(year) - day;
30107 		DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
30108 		if (diff_days <= 0) {
30109 			DUK_ASSERT(-diff_days < 366);  /* fits into duk_small_int_t */
30110 			*out_day_within_year = -diff_days;
30111 			DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
30112 			                     (long) year, (long) *out_day_within_year));
30113 			DUK_ASSERT(*out_day_within_year >= 0);
30114 			DUK_ASSERT(*out_day_within_year < (duk_bi_date_is_leap_year(year) ? 366 : 365));
30115 			return year;
30116 		}
30117 
30118 		/* Note: this is very tricky; we must never 'overshoot' the
30119 		 * correction downwards.
30120 		 */
30121 		year -= 1 + (diff_days - 1) / 366;  /* conservative */
30122 	}
30123 }
30124 
30125 /* Given a (year, month, day-within-month) triple, compute day number.
30126  * The input triple is un-normalized and may contain non-finite values.
30127  */
duk__make_day(duk_double_t year,duk_double_t month,duk_double_t day)30128 DUK_LOCAL duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_double_t day) {
30129 	duk_int_t day_num;
30130 	duk_bool_t is_leap;
30131 	duk_small_int_t i, n;
30132 
30133 	/* Assume that year, month, day are all coerced to whole numbers.
30134 	 * They may also be NaN or infinity, in which case this function
30135 	 * must return NaN or infinity to ensure time value becomes NaN.
30136 	 * If 'day' is NaN, the final return will end up returning a NaN,
30137 	 * so it doesn't need to be checked here.
30138 	 */
30139 
30140 	if (!DUK_ISFINITE(year) || !DUK_ISFINITE(month)) {
30141 		return DUK_DOUBLE_NAN;
30142 	}
30143 
30144 	year += DUK_FLOOR(month / 12.0);
30145 
30146 	month = DUK_FMOD(month, 12.0);
30147 	if (month < 0.0) {
30148 		/* handle negative values */
30149 		month += 12.0;
30150 	}
30151 
30152 	/* The algorithm in E5.1 Section 15.9.1.12 normalizes month, but
30153 	 * does not normalize the day-of-month (nor check whether or not
30154 	 * it is finite) because it's not necessary for finding the day
30155 	 * number which matches the (year,month) pair.
30156 	 *
30157 	 * We assume that duk__day_from_year() is exact here.
30158 	 *
30159 	 * Without an explicit infinity / NaN check in the beginning,
30160 	 * day_num would be a bogus integer here.
30161 	 *
30162 	 * It's possible for 'year' to be out of integer range here.
30163 	 * If so, we need to return NaN without integer overflow.
30164 	 * This fixes test-bug-setyear-overflow.js.
30165 	 */
30166 
30167 	if (!duk_bi_date_year_in_valid_range(year)) {
30168 		DUK_DD(DUK_DDPRINT("year not in ecmascript valid range, avoid integer overflow: %lf", (double) year));
30169 		return DUK_DOUBLE_NAN;
30170 	}
30171 	day_num = duk__day_from_year((duk_int_t) year);
30172 	is_leap = duk_bi_date_is_leap_year((duk_int_t) year);
30173 
30174 	n = (duk_small_int_t) month;
30175 	for (i = 0; i < n; i++) {
30176 		day_num += duk__days_in_month[i];
30177 		if (i == 1 && is_leap) {
30178 			day_num++;
30179 		}
30180 	}
30181 
30182 	/* If 'day' is NaN, returns NaN. */
30183 	return (duk_double_t) day_num + day;
30184 }
30185 
30186 /* Split time value into parts.  The time value may contain fractions (it may
30187  * come from duk_time_to_components() API call) which are truncated.  Possible
30188  * local time adjustment has already been applied when reading the time value.
30189  */
duk_bi_date_timeval_to_parts(duk_double_t d,duk_int_t * parts,duk_double_t * dparts,duk_small_uint_t flags)30190 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) {
30191 	duk_double_t d1, d2;
30192 	duk_int_t t1, t2;
30193 	duk_int_t day_since_epoch;
30194 	duk_int_t year;  /* does not fit into 16 bits */
30195 	duk_small_int_t day_in_year;
30196 	duk_small_int_t month;
30197 	duk_small_int_t day;
30198 	duk_small_int_t dim;
30199 	duk_int_t jan1_since_epoch;
30200 	duk_small_int_t jan1_weekday;
30201 	duk_int_t equiv_year;
30202 	duk_small_uint_t i;
30203 	duk_bool_t is_leap;
30204 	duk_small_int_t arridx;
30205 
30206 	DUK_ASSERT(DUK_ISFINITE(d));    /* caller checks */
30207 	d = DUK_FLOOR(d);  /* remove fractions if present */
30208 	DUK_ASSERT(DUK_FLOOR(d) == d);
30209 
30210 	/* The timevalue must be in valid ECMAScript range, but since a local
30211 	 * time offset can be applied, we need to allow a +/- 24h leeway to
30212 	 * the value.  In other words, although the UTC time is within the
30213 	 * ECMAScript range, the local part values can be just outside of it.
30214 	 */
30215 	DUK_UNREF(duk_bi_date_timeval_in_leeway_range);
30216 	DUK_ASSERT(duk_bi_date_timeval_in_leeway_range(d));
30217 
30218 	/* These computations are guaranteed to be exact for the valid
30219 	 * E5 time value range, assuming milliseconds without fractions.
30220 	 */
30221 	d1 = (duk_double_t) DUK_FMOD(d, (double) DUK_DATE_MSEC_DAY);
30222 	if (d1 < 0.0) {
30223 		/* deal with negative values */
30224 		d1 += (duk_double_t) DUK_DATE_MSEC_DAY;
30225 	}
30226 	d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK_DATE_MSEC_DAY));
30227 	DUK_ASSERT(d2 * ((duk_double_t) DUK_DATE_MSEC_DAY) + d1 == d);
30228 	/* now expected to fit into a 32-bit integer */
30229 	t1 = (duk_int_t) d1;
30230 	t2 = (duk_int_t) d2;
30231 	day_since_epoch = t2;
30232 	DUK_ASSERT((duk_double_t) t1 == d1);
30233 	DUK_ASSERT((duk_double_t) t2 == d2);
30234 
30235 	/* t1 = milliseconds within day (fits 32 bit)
30236 	 * t2 = day number from epoch (fits 32 bit, may be negative)
30237 	 */
30238 
30239 	parts[DUK_DATE_IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
30240 	parts[DUK_DATE_IDX_SECOND] = t1 % 60; t1 /= 60;
30241 	parts[DUK_DATE_IDX_MINUTE] = t1 % 60; t1 /= 60;
30242 	parts[DUK_DATE_IDX_HOUR] = t1;
30243 	DUK_ASSERT(parts[DUK_DATE_IDX_MILLISECOND] >= 0 && parts[DUK_DATE_IDX_MILLISECOND] <= 999);
30244 	DUK_ASSERT(parts[DUK_DATE_IDX_SECOND] >= 0 && parts[DUK_DATE_IDX_SECOND] <= 59);
30245 	DUK_ASSERT(parts[DUK_DATE_IDX_MINUTE] >= 0 && parts[DUK_DATE_IDX_MINUTE] <= 59);
30246 	DUK_ASSERT(parts[DUK_DATE_IDX_HOUR] >= 0 && parts[DUK_DATE_IDX_HOUR] <= 23);
30247 
30248 	DUK_DDD(DUK_DDDPRINT("d=%lf, d1=%lf, d2=%lf, t1=%ld, t2=%ld, parts: hour=%ld min=%ld sec=%ld msec=%ld",
30249 	                     (double) d, (double) d1, (double) d2, (long) t1, (long) t2,
30250 	                     (long) parts[DUK_DATE_IDX_HOUR],
30251 	                     (long) parts[DUK_DATE_IDX_MINUTE],
30252 	                     (long) parts[DUK_DATE_IDX_SECOND],
30253 	                     (long) parts[DUK_DATE_IDX_MILLISECOND]));
30254 
30255 	/* This assert depends on the input parts representing time inside
30256 	 * the ECMAScript range.
30257 	 */
30258 	DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
30259 	parts[DUK_DATE_IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30260 	DUK_ASSERT(parts[DUK_DATE_IDX_WEEKDAY] >= 0 && parts[DUK_DATE_IDX_WEEKDAY] <= 6);
30261 
30262 	year = duk__year_from_day(t2, &day_in_year);
30263 	day = day_in_year;
30264 	is_leap = duk_bi_date_is_leap_year(year);
30265 	for (month = 0; month < 12; month++) {
30266 		dim = duk__days_in_month[month];
30267 		if (month == 1 && is_leap) {
30268 			dim++;
30269 		}
30270 		DUK_DDD(DUK_DDDPRINT("month=%ld, dim=%ld, day=%ld",
30271 		                     (long) month, (long) dim, (long) day));
30272 		if (day < dim) {
30273 			break;
30274 		}
30275 		day -= dim;
30276 	}
30277 	DUK_DDD(DUK_DDDPRINT("final month=%ld", (long) month));
30278 	DUK_ASSERT(month >= 0 && month <= 11);
30279 	DUK_ASSERT(day >= 0 && day <= 31);
30280 
30281 	/* Equivalent year mapping, used to avoid DST trouble when platform
30282 	 * may fail to provide reasonable DST answers for dates outside the
30283 	 * ordinary range (e.g. 1970-2038).  An equivalent year has the same
30284 	 * leap-year-ness as the original year and begins on the same weekday
30285 	 * (Jan 1).
30286 	 *
30287 	 * The year 2038 is avoided because there seem to be problems with it
30288 	 * on some platforms.  The year 1970 is also avoided as there were
30289 	 * practical problems with it; an equivalent year is used for it too,
30290 	 * which breaks some DST computations for 1970 right now, see e.g.
30291 	 * test-bi-date-tzoffset-brute-fi.js.
30292 	 */
30293 	if ((flags & DUK_DATE_FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
30294 		DUK_ASSERT(is_leap == 0 || is_leap == 1);
30295 
30296 		jan1_since_epoch = day_since_epoch - day_in_year;  /* day number for Jan 1 since epoch */
30297 		DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
30298 		jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7;  /* E5.1 Section 15.9.1.6 */
30299 		DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
30300 		arridx = jan1_weekday;
30301 		if (is_leap) {
30302 			arridx += 7;
30303 		}
30304 		DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
30305 
30306 		equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
30307 		year = equiv_year;
30308 		DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
30309 		                     "jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
30310 		                     (long) year, (long) day_in_year, (long) day_since_epoch,
30311 		                     (long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
30312 	}
30313 
30314 	parts[DUK_DATE_IDX_YEAR] = year;
30315 	parts[DUK_DATE_IDX_MONTH] = month;
30316 	parts[DUK_DATE_IDX_DAY] = day;
30317 
30318 	if (flags & DUK_DATE_FLAG_ONEBASED) {
30319 		parts[DUK_DATE_IDX_MONTH]++;  /* zero-based -> one-based */
30320 		parts[DUK_DATE_IDX_DAY]++;    /* -""- */
30321 	}
30322 
30323 	if (dparts != NULL) {
30324 		for (i = 0; i < DUK_DATE_IDX_NUM_PARTS; i++) {
30325 			dparts[i] = (duk_double_t) parts[i];
30326 		}
30327 	}
30328 }
30329 
30330 /* Compute time value from (double) parts.  The parts can be either UTC
30331  * or local time; if local, they need to be (conceptually) converted into
30332  * UTC time.  The parts may represent valid or invalid time, and may be
30333  * wildly out of range (but may cancel each other and still come out in
30334  * the valid Date range).
30335  */
duk_bi_date_get_timeval_from_dparts(duk_double_t * dparts,duk_small_uint_t flags)30336 DUK_INTERNAL duk_double_t duk_bi_date_get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
30337 #if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
30338 	/* See comments below on MakeTime why these are volatile. */
30339 	volatile duk_double_t tmp_time;
30340 	volatile duk_double_t tmp_day;
30341 	volatile duk_double_t d;
30342 #else
30343 	duk_double_t tmp_time;
30344 	duk_double_t tmp_day;
30345 	duk_double_t d;
30346 #endif
30347 	duk_small_uint_t i;
30348 	duk_int_t tzoff, tzoffprev1, tzoffprev2;
30349 
30350 	/* Expects 'this' at top of stack on entry. */
30351 
30352 	/* Coerce all finite parts with ToInteger().  ToInteger() must not
30353 	 * be called for NaN/Infinity because it will convert e.g. NaN to
30354 	 * zero.  If ToInteger() has already been called, this has no side
30355 	 * effects and is idempotent.
30356 	 *
30357 	 * Don't read dparts[DUK_DATE_IDX_WEEKDAY]; it will cause Valgrind
30358 	 * issues if the value is uninitialized.
30359 	 */
30360 	for (i = 0; i <= DUK_DATE_IDX_MILLISECOND; i++) {
30361 		/* SCANBUILD: scan-build complains here about assigned value
30362 		 * being garbage or undefined.  This is correct but operating
30363 		 * on undefined values has no ill effect and is ignored by the
30364 		 * caller in the case where this happens.
30365 		 */
30366 		d = dparts[i];
30367 		if (DUK_ISFINITE(d)) {
30368 			dparts[i] = duk_js_tointeger_number(d);
30369 		}
30370 	}
30371 
30372 	/* Use explicit steps in computation to try to ensure that
30373 	 * computation happens with intermediate results coerced to
30374 	 * double values (instead of using something more accurate).
30375 	 * E.g. E5.1 Section 15.9.1.11 requires use of IEEE 754
30376 	 * rules (= ECMAScript '+' and '*' operators).
30377 	 *
30378 	 * Without 'volatile' even this approach fails on some platform
30379 	 * and compiler combinations.  For instance, gcc 4.8.1 on Ubuntu
30380 	 * 64-bit, with -m32 and without -std=c99, test-bi-date-canceling.js
30381 	 * would fail because of some optimizations when computing tmp_time
30382 	 * (MakeTime below).  Adding 'volatile' to tmp_time solved this
30383 	 * particular problem (annoyingly, also adding debug prints or
30384 	 * running the executable under valgrind hides it).
30385 	 */
30386 
30387 	/* MakeTime */
30388 	tmp_time = 0.0;
30389 	tmp_time += dparts[DUK_DATE_IDX_HOUR] * ((duk_double_t) DUK_DATE_MSEC_HOUR);
30390 	tmp_time += dparts[DUK_DATE_IDX_MINUTE] * ((duk_double_t) DUK_DATE_MSEC_MINUTE);
30391 	tmp_time += dparts[DUK_DATE_IDX_SECOND] * ((duk_double_t) DUK_DATE_MSEC_SECOND);
30392 	tmp_time += dparts[DUK_DATE_IDX_MILLISECOND];
30393 
30394 	/* MakeDay */
30395 	tmp_day = duk__make_day(dparts[DUK_DATE_IDX_YEAR], dparts[DUK_DATE_IDX_MONTH], dparts[DUK_DATE_IDX_DAY]);
30396 
30397 	/* MakeDate */
30398 	d = tmp_day * ((duk_double_t) DUK_DATE_MSEC_DAY) + tmp_time;
30399 
30400 	DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
30401 	                     (double) tmp_time, (double) tmp_day, (double) d));
30402 
30403 	/* Optional UTC conversion. */
30404 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30405 		/* DUK_USE_DATE_GET_LOCAL_TZOFFSET() needs to be called with a
30406 		 * time value computed from UTC parts.  At this point we only
30407 		 * have 'd' which is a time value computed from local parts, so
30408 		 * it is off by the UTC-to-local time offset which we don't know
30409 		 * yet.  The current solution for computing the UTC-to-local
30410 		 * time offset is to iterate a few times and detect a fixed
30411 		 * point or a two-cycle loop (or a sanity iteration limit),
30412 		 * see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
30413 		 *
30414 		 * E5.1 Section 15.9.1.9:
30415 		 * UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
30416 		 *
30417 		 * For NaN/inf, DUK_USE_DATE_GET_LOCAL_TZOFFSET() returns 0.
30418 		 */
30419 
30420 #if 0
30421 		/* Old solution: don't iterate, incorrect */
30422 		tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
30423 		DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
30424 		d -= tzoff * 1000L;
30425 		DUK_UNREF(tzoffprev1);
30426 		DUK_UNREF(tzoffprev2);
30427 #endif
30428 
30429 		/* Iteration solution */
30430 		tzoff = 0;
30431 		tzoffprev1 = 999999999L;  /* invalid value which never matches */
30432 		for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
30433 			tzoffprev2 = tzoffprev1;
30434 			tzoffprev1 = tzoff;
30435 			tzoff = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
30436 			DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
30437 			                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30438 			if (tzoff == tzoffprev1) {
30439 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30440 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30441 				break;
30442 			} else if (tzoff == tzoffprev2) {
30443 				/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
30444 				 * In these cases, favor a higher tzoffset to get a consistent
30445 				 * result which is independent of iteration count.  Not sure if
30446 				 * this is a generically correct solution.
30447 				 */
30448 				DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
30449 				                     (int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
30450 				if (tzoffprev1 > tzoff) {
30451 					tzoff = tzoffprev1;
30452 				}
30453 				break;
30454 			}
30455 		}
30456 		DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
30457 		d -= tzoff * 1000L;
30458 	}
30459 
30460 	/* TimeClip(), which also handles Infinity -> NaN conversion */
30461 	d = duk__timeclip(d);
30462 
30463 	return d;
30464 }
30465 
30466 /*
30467  *  API oriented helpers
30468  */
30469 
30470 /* Push 'this' binding, check that it is a Date object; then push the
30471  * internal time value.  At the end, stack is: [ ... this timeval ].
30472  * Returns the time value.  Local time adjustment is done if requested.
30473  */
duk__push_this_get_timeval_tzoffset(duk_hthread * thr,duk_small_uint_t flags,duk_int_t * out_tzoffset)30474 DUK_LOCAL duk_double_t duk__push_this_get_timeval_tzoffset(duk_hthread *thr, duk_small_uint_t flags, duk_int_t *out_tzoffset) {
30475 	duk_hobject *h;
30476 	duk_double_t d;
30477 	duk_int_t tzoffset = 0;
30478 
30479 	duk_push_this(thr);
30480 	h = duk_get_hobject(thr, -1);  /* XXX: getter with class check, useful in built-ins */
30481 	if (h == NULL || DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_DATE) {
30482 		DUK_ERROR_TYPE(thr, "expected Date");
30483 		DUK_WO_NORETURN(return 0.0;);
30484 	}
30485 
30486 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
30487 	d = duk_to_number_m1(thr);
30488 	duk_pop(thr);
30489 
30490 	if (DUK_ISNAN(d)) {
30491 		if (flags & DUK_DATE_FLAG_NAN_TO_ZERO) {
30492 			d = 0.0;
30493 		}
30494 		if (flags & DUK_DATE_FLAG_NAN_TO_RANGE_ERROR) {
30495 			DUK_ERROR_RANGE(thr, "Invalid Date");
30496 			DUK_WO_NORETURN(return 0.0;);
30497 		}
30498 	}
30499 	/* if no NaN handling flag, may still be NaN here, but not Inf */
30500 	DUK_ASSERT(!DUK_ISINF(d));
30501 
30502 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30503 		/* Note: DST adjustment is determined using UTC time.
30504 		 * If 'd' is NaN, tzoffset will be 0.
30505 		 */
30506 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);  /* seconds */
30507 		d += tzoffset * 1000L;
30508 	}
30509 	if (out_tzoffset) {
30510 		*out_tzoffset = tzoffset;
30511 	}
30512 
30513 	/* [ ... this ] */
30514 	return d;
30515 }
30516 
duk__push_this_get_timeval(duk_hthread * thr,duk_small_uint_t flags)30517 DUK_LOCAL duk_double_t duk__push_this_get_timeval(duk_hthread *thr, duk_small_uint_t flags) {
30518 	return duk__push_this_get_timeval_tzoffset(thr, flags, NULL);
30519 }
30520 
30521 /* Set timeval to 'this' from dparts, push the new time value onto the
30522  * value stack and return 1 (caller can then tail call us).  Expects
30523  * the value stack to contain 'this' on the stack top.
30524  */
duk__set_this_timeval_from_dparts(duk_hthread * thr,duk_double_t * dparts,duk_small_uint_t flags)30525 DUK_LOCAL duk_ret_t duk__set_this_timeval_from_dparts(duk_hthread *thr, duk_double_t *dparts, duk_small_uint_t flags) {
30526 	duk_double_t d;
30527 
30528 	/* [ ... this ] */
30529 
30530 	d = duk_bi_date_get_timeval_from_dparts(dparts, flags);
30531 	duk_push_number(thr, d);  /* -> [ ... this timeval_new ] */
30532 	duk_dup_top(thr);         /* -> [ ... this timeval_new timeval_new ] */
30533 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE);
30534 
30535 	/* stack top: new time value, return 1 to allow tail calls */
30536 	return 1;
30537 }
30538 
30539 /* '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)30540 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) {
30541 	char yearstr[8];   /* "-123456\0" */
30542 	char tzstr[8];     /* "+11:22\0" */
30543 	char sep = (flags & DUK_DATE_FLAG_SEP_T) ? DUK_ASC_UC_T : DUK_ASC_SPACE;
30544 
30545 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30546 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30547 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= -999999 && parts[DUK_DATE_IDX_YEAR] <= 999999);
30548 
30549 	/* Note: %06d for positive value, %07d for negative value to include
30550 	 * sign and 6 digits.
30551 	 */
30552 	DUK_SNPRINTF(yearstr,
30553 	             sizeof(yearstr),
30554 	             (parts[DUK_DATE_IDX_YEAR] >= 0 && parts[DUK_DATE_IDX_YEAR] <= 9999) ? "%04ld" :
30555 	                    ((parts[DUK_DATE_IDX_YEAR] >= 0) ? "+%06ld" : "%07ld"),
30556 	             (long) parts[DUK_DATE_IDX_YEAR]);
30557 	yearstr[sizeof(yearstr) - 1] = (char) 0;
30558 
30559 	if (flags & DUK_DATE_FLAG_LOCALTIME) {
30560 		/* tzoffset seconds are dropped; 16 bits suffice for
30561 		 * time offset in minutes
30562 		 */
30563 		const char *fmt;
30564 		duk_small_int_t tmp, arg_hours, arg_minutes;
30565 
30566 		if (tzoffset >= 0) {
30567 			tmp = tzoffset;
30568 			fmt = "+%02d:%02d";
30569 		} else {
30570 			tmp = -tzoffset;
30571 			fmt = "-%02d:%02d";
30572 		}
30573 		tmp = tmp / 60;
30574 		arg_hours = tmp / 60;
30575 		arg_minutes = tmp % 60;
30576 		DUK_ASSERT(arg_hours <= 24);  /* Even less is actually guaranteed for a valid tzoffset. */
30577 		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. */
30578 
30579 		DUK_SNPRINTF(tzstr, sizeof(tzstr), fmt, (int) arg_hours, (int) arg_minutes);
30580 		tzstr[sizeof(tzstr) - 1] = (char) 0;
30581 	} else {
30582 		tzstr[0] = DUK_ASC_UC_Z;
30583 		tzstr[1] = (char) 0;
30584 	}
30585 
30586 	/* Unlike year, the other parts fit into 16 bits so %d format
30587 	 * is portable.
30588 	 */
30589 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
30590 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d%c%02d:%02d:%02d.%03d%s",
30591 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY], (int) sep,
30592 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30593 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND], (const char *) tzstr);
30594 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
30595 		DUK_SPRINTF((char *) out_buf, "%s-%02d-%02d",
30596 		            (const char *) yearstr, (int) parts[DUK_DATE_IDX_MONTH], (int) parts[DUK_DATE_IDX_DAY]);
30597 	} else {
30598 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
30599 		DUK_SPRINTF((char *) out_buf, "%02d:%02d:%02d.%03d%s",
30600 		            (int) parts[DUK_DATE_IDX_HOUR], (int) parts[DUK_DATE_IDX_MINUTE],
30601 		            (int) parts[DUK_DATE_IDX_SECOND], (int) parts[DUK_DATE_IDX_MILLISECOND],
30602 		            (const char *) tzstr);
30603 	}
30604 }
30605 
30606 /* Helper for string conversion calls: check 'this' binding, get the
30607  * internal time value, and format date and/or time in a few formats.
30608  * Return value allows tail calls.
30609  */
duk__to_string_helper(duk_hthread * thr,duk_small_uint_t flags)30610 DUK_LOCAL duk_ret_t duk__to_string_helper(duk_hthread *thr, duk_small_uint_t flags) {
30611 	duk_double_t d;
30612 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30613 	duk_int_t tzoffset;  /* seconds, doesn't fit into 16 bits */
30614 	duk_bool_t rc;
30615 	duk_uint8_t buf[DUK_BI_DATE_ISO8601_BUFSIZE];
30616 
30617 	DUK_UNREF(rc);  /* unreferenced with some options */
30618 
30619 	d = duk__push_this_get_timeval_tzoffset(thr, flags, &tzoffset);
30620 	if (DUK_ISNAN(d)) {
30621 		duk_push_hstring_stridx(thr, DUK_STRIDX_INVALID_DATE);
30622 		return 1;
30623 	}
30624 	DUK_ASSERT(DUK_ISFINITE(d));
30625 
30626 	/* formatters always get one-based month/day-of-month */
30627 	duk_bi_date_timeval_to_parts(d, parts, NULL, DUK_DATE_FLAG_ONEBASED);
30628 	DUK_ASSERT(parts[DUK_DATE_IDX_MONTH] >= 1 && parts[DUK_DATE_IDX_MONTH] <= 12);
30629 	DUK_ASSERT(parts[DUK_DATE_IDX_DAY] >= 1 && parts[DUK_DATE_IDX_DAY] <= 31);
30630 
30631 	if (flags & DUK_DATE_FLAG_TOSTRING_LOCALE) {
30632 		/* try locale specific formatter; if it refuses to format the
30633 		 * string, fall back to an ISO 8601 formatted value in local
30634 		 * time.
30635 		 */
30636 #if defined(DUK_USE_DATE_FORMAT_STRING)
30637 		/* Contract, either:
30638 		 * - Push string to value stack and return 1
30639 		 * - Don't push anything and return 0
30640 		 */
30641 
30642 		rc = DUK_USE_DATE_FORMAT_STRING(thr, parts, tzoffset, flags);
30643 		if (rc != 0) {
30644 			return 1;
30645 		}
30646 #else
30647 		/* No locale specific formatter; this is OK, we fall back
30648 		 * to ISO 8601.
30649 		 */
30650 #endif
30651 	}
30652 
30653 	/* Different calling convention than above used because the helper
30654 	 * is shared.
30655 	 */
30656 	duk__format_parts_iso8601(parts, tzoffset, flags, buf);
30657 	duk_push_string(thr, (const char *) buf);
30658 	return 1;
30659 }
30660 
30661 /* Helper for component getter calls: check 'this' binding, get the
30662  * internal time value, split it into parts (either as UTC time or
30663  * local time), push a specified component as a return value to the
30664  * value stack and return 1 (caller can then tail call us).
30665  */
duk__get_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_idx)30666 DUK_LOCAL duk_ret_t duk__get_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_idx) {
30667 	duk_double_t d;
30668 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30669 	duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30670 
30671 	DUK_ASSERT_DISABLE(idx_part >= 0);  /* unsigned */
30672 	DUK_ASSERT(idx_part < DUK_DATE_IDX_NUM_PARTS);
30673 
30674 	d = duk__push_this_get_timeval(thr, flags_and_idx);
30675 	if (DUK_ISNAN(d)) {
30676 		duk_push_nan(thr);
30677 		return 1;
30678 	}
30679 	DUK_ASSERT(DUK_ISFINITE(d));
30680 
30681 	duk_bi_date_timeval_to_parts(d, parts, NULL, flags_and_idx);  /* no need to mask idx portion */
30682 
30683 	/* Setter APIs detect special year numbers (0...99) and apply a +1900
30684 	 * only in certain cases.  The legacy getYear() getter applies -1900
30685 	 * unconditionally.
30686 	 */
30687 	duk_push_int(thr, (flags_and_idx & DUK_DATE_FLAG_SUB1900) ? parts[idx_part] - 1900 : parts[idx_part]);
30688 	return 1;
30689 }
30690 
30691 /* Helper for component setter calls: check 'this' binding, get the
30692  * internal time value, split it into parts (either as UTC time or
30693  * local time), modify one or more components as specified, recompute
30694  * the time value, set it as the internal value.  Finally, push the
30695  * new time value as a return value to the value stack and return 1
30696  * (caller can then tail call us).
30697  */
duk__set_part_helper(duk_hthread * thr,duk_small_uint_t flags_and_maxnargs)30698 DUK_LOCAL duk_ret_t duk__set_part_helper(duk_hthread *thr, duk_small_uint_t flags_and_maxnargs) {
30699 	duk_double_t d;
30700 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
30701 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
30702 	duk_idx_t nargs;
30703 	duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK_DATE_FLAG_VALUE_SHIFT);  /* unpack args */
30704 	duk_small_uint_t idx_first, idx;
30705 	duk_small_uint_t i;
30706 
30707 	nargs = duk_get_top(thr);
30708 	d = duk__push_this_get_timeval(thr, flags_and_maxnargs);
30709 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
30710 
30711 	if (DUK_ISFINITE(d)) {
30712 		duk_bi_date_timeval_to_parts(d, parts, dparts, flags_and_maxnargs);
30713 	} else {
30714 		/* NaN timevalue: we need to coerce the arguments, but
30715 		 * the resulting internal timestamp needs to remain NaN.
30716 		 * This works but is not pretty: parts and dparts will
30717 		 * be partially uninitialized, but we only write to them.
30718 		 */
30719 	}
30720 
30721 	/*
30722 	 *  Determining which datetime components to overwrite based on
30723 	 *  stack arguments is a bit complicated, but important to factor
30724 	 *  out from setters themselves for compactness.
30725 	 *
30726 	 *  If DUK_DATE_FLAG_TIMESETTER, maxnargs indicates setter type:
30727 	 *
30728 	 *   1 -> millisecond
30729 	 *   2 -> second, [millisecond]
30730 	 *   3 -> minute, [second], [millisecond]
30731 	 *   4 -> hour, [minute], [second], [millisecond]
30732 	 *
30733 	 *  Else:
30734 	 *
30735 	 *   1 -> date
30736 	 *   2 -> month, [date]
30737 	 *   3 -> year, [month], [date]
30738 	 *
30739 	 *  By comparing nargs and maxnargs (and flags) we know which
30740 	 *  components to override.  We rely on part index ordering.
30741 	 */
30742 
30743 	if (flags_and_maxnargs & DUK_DATE_FLAG_TIMESETTER) {
30744 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 4);
30745 		idx_first = DUK_DATE_IDX_MILLISECOND - (maxnargs - 1);
30746 	} else {
30747 		DUK_ASSERT(maxnargs >= 1 && maxnargs <= 3);
30748 		idx_first = DUK_DATE_IDX_DAY - (maxnargs - 1);
30749 	}
30750 	DUK_ASSERT_DISABLE(idx_first >= 0);  /* unsigned */
30751 	DUK_ASSERT(idx_first < DUK_DATE_IDX_NUM_PARTS);
30752 
30753 	for (i = 0; i < maxnargs; i++) {
30754 		if ((duk_idx_t) i >= nargs) {
30755 			/* no argument given -> leave components untouched */
30756 			break;
30757 		}
30758 		idx = idx_first + i;
30759 		DUK_ASSERT_DISABLE(idx >= 0);  /* unsigned */
30760 		DUK_ASSERT(idx < DUK_DATE_IDX_NUM_PARTS);
30761 
30762 		if (idx == DUK_DATE_IDX_YEAR && (flags_and_maxnargs & DUK_DATE_FLAG_YEAR_FIXUP)) {
30763 			duk__twodigit_year_fixup(thr, (duk_idx_t) i);
30764 		}
30765 
30766 		dparts[idx] = duk_to_number(thr, (duk_idx_t) i);
30767 
30768 		if (idx == DUK_DATE_IDX_DAY) {
30769 			/* Day-of-month is one-based in the API, but zero-based
30770 			 * internally, so fix here.  Note that month is zero-based
30771 			 * both in the API and internally.
30772 			 */
30773 			/* SCANBUILD: complains about use of uninitialized values.
30774 			 * The complaint is correct, but operating in undefined
30775 			 * values here is intentional in some cases and the caller
30776 			 * ignores the results.
30777 			 */
30778 			dparts[idx] -= 1.0;
30779 		}
30780 	}
30781 
30782 	/* Leaves new timevalue on stack top and returns 1, which is correct
30783 	 * for part setters.
30784 	 */
30785 	if (DUK_ISFINITE(d)) {
30786 		return duk__set_this_timeval_from_dparts(thr, dparts, flags_and_maxnargs);
30787 	} else {
30788 		/* Internal timevalue is already NaN, so don't touch it. */
30789 		duk_push_nan(thr);
30790 		return 1;
30791 	}
30792 }
30793 
30794 /* Apply ToNumber() to specified index; if ToInteger(val) in [0,99], add
30795  * 1900 and replace value at idx_val.
30796  */
duk__twodigit_year_fixup(duk_hthread * thr,duk_idx_t idx_val)30797 DUK_LOCAL void duk__twodigit_year_fixup(duk_hthread *thr, duk_idx_t idx_val) {
30798 	duk_double_t d;
30799 
30800 	/* XXX: idx_val would fit into 16 bits, but using duk_small_uint_t
30801 	 * might not generate better code due to casting.
30802 	 */
30803 
30804 	/* E5 Sections 15.9.3.1, B.2.4, B.2.5 */
30805 	duk_to_number(thr, idx_val);
30806 	if (duk_is_nan(thr, idx_val)) {
30807 		return;
30808 	}
30809 	duk_dup(thr, idx_val);
30810 	duk_to_int(thr, -1);
30811 	d = duk_get_number(thr, -1);  /* get as double to handle huge numbers correctly */
30812 	if (d >= 0.0 && d <= 99.0) {
30813 		d += 1900.0;
30814 		duk_push_number(thr, d);
30815 		duk_replace(thr, idx_val);
30816 	}
30817 	duk_pop(thr);
30818 }
30819 
30820 /* Set datetime parts from stack arguments, defaulting any missing values.
30821  * Day-of-week is not set; it is not required when setting the time value.
30822  */
duk__set_parts_from_args(duk_hthread * thr,duk_double_t * dparts,duk_idx_t nargs)30823 DUK_LOCAL void duk__set_parts_from_args(duk_hthread *thr, duk_double_t *dparts, duk_idx_t nargs) {
30824 	duk_double_t d;
30825 	duk_small_uint_t i;
30826 	duk_small_uint_t idx;
30827 
30828 	/* Causes a ToNumber() coercion, but doesn't break coercion order since
30829 	 * year is coerced first anyway.
30830 	 */
30831 	duk__twodigit_year_fixup(thr, 0);
30832 
30833 	/* There are at most 7 args, but we use 8 here so that also
30834 	 * DUK_DATE_IDX_WEEKDAY gets initialized (to zero) to avoid the potential
30835 	 * for any Valgrind gripes later.
30836 	 */
30837 	for (i = 0; i < 8; i++) {
30838 		/* Note: rely on index ordering */
30839 		idx = DUK_DATE_IDX_YEAR + i;
30840 		if ((duk_idx_t) i < nargs) {
30841 			d = duk_to_number(thr, (duk_idx_t) i);
30842 			if (idx == DUK_DATE_IDX_DAY) {
30843 				/* Convert day from one-based to zero-based (internal).  This may
30844 				 * cause the day part to be negative, which is OK.
30845 				 */
30846 				d -= 1.0;
30847 			}
30848 		} else {
30849 			/* All components default to 0 except day-of-month which defaults
30850 			 * to 1.  However, because our internal day-of-month is zero-based,
30851 			 * it also defaults to zero here.
30852 			 */
30853 			d = 0.0;
30854 		}
30855 		dparts[idx] = d;
30856 	}
30857 
30858 	DUK_DDD(DUK_DDDPRINT("parts from args -> %lf %lf %lf %lf %lf %lf %lf %lf",
30859 	                     (double) dparts[0], (double) dparts[1],
30860 	                     (double) dparts[2], (double) dparts[3],
30861 	                     (double) dparts[4], (double) dparts[5],
30862 	                     (double) dparts[6], (double) dparts[7]));
30863 }
30864 
30865 /*
30866  *  Indirect magic value lookup for Date methods.
30867  *
30868  *  Date methods don't put their control flags into the function magic value
30869  *  because they wouldn't fit into a LIGHTFUNC's magic field.  Instead, the
30870  *  magic value is set to an index pointing to the array of control flags
30871  *  below.
30872  *
30873  *  This must be kept in strict sync with genbuiltins.py!
30874  */
30875 
30876 static duk_uint16_t duk__date_magics[] = {
30877 	/* 0: toString */
30878 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
30879 
30880 	/* 1: toDateString */
30881 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_LOCALTIME,
30882 
30883 	/* 2: toTimeString */
30884 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_LOCALTIME,
30885 
30886 	/* 3: toLocaleString */
30887 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30888 
30889 	/* 4: toLocaleDateString */
30890 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30891 
30892 	/* 5: toLocaleTimeString */
30893 	DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_TOSTRING_LOCALE + DUK_DATE_FLAG_LOCALTIME,
30894 
30895 	/* 6: toUTCString */
30896 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME,
30897 
30898 	/* 7: toISOString */
30899 	DUK_DATE_FLAG_TOSTRING_DATE + DUK_DATE_FLAG_TOSTRING_TIME + DUK_DATE_FLAG_NAN_TO_RANGE_ERROR + DUK_DATE_FLAG_SEP_T,
30900 
30901 	/* 8: getFullYear */
30902 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30903 
30904 	/* 9: getUTCFullYear */
30905 	0 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30906 
30907 	/* 10: getMonth */
30908 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
30909 
30910 	/* 11: getUTCMonth */
30911 	0 + (DUK_DATE_IDX_MONTH << DUK_DATE_FLAG_VALUE_SHIFT),
30912 
30913 	/* 12: getDate */
30914 	DUK_DATE_FLAG_ONEBASED + DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
30915 
30916 	/* 13: getUTCDate */
30917 	DUK_DATE_FLAG_ONEBASED + (DUK_DATE_IDX_DAY << DUK_DATE_FLAG_VALUE_SHIFT),
30918 
30919 	/* 14: getDay */
30920 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
30921 
30922 	/* 15: getUTCDay */
30923 	0 + (DUK_DATE_IDX_WEEKDAY << DUK_DATE_FLAG_VALUE_SHIFT),
30924 
30925 	/* 16: getHours */
30926 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
30927 
30928 	/* 17: getUTCHours */
30929 	0 + (DUK_DATE_IDX_HOUR << DUK_DATE_FLAG_VALUE_SHIFT),
30930 
30931 	/* 18: getMinutes */
30932 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
30933 
30934 	/* 19: getUTCMinutes */
30935 	0 + (DUK_DATE_IDX_MINUTE << DUK_DATE_FLAG_VALUE_SHIFT),
30936 
30937 	/* 20: getSeconds */
30938 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30939 
30940 	/* 21: getUTCSeconds */
30941 	0 + (DUK_DATE_IDX_SECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30942 
30943 	/* 22: getMilliseconds */
30944 	DUK_DATE_FLAG_LOCALTIME + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30945 
30946 	/* 23: getUTCMilliseconds */
30947 	0 + (DUK_DATE_IDX_MILLISECOND << DUK_DATE_FLAG_VALUE_SHIFT),
30948 
30949 	/* 24: setMilliseconds */
30950 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30951 
30952 	/* 25: setUTCMilliseconds */
30953 	DUK_DATE_FLAG_TIMESETTER + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30954 
30955 	/* 26: setSeconds */
30956 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30957 
30958 	/* 27: setUTCSeconds */
30959 	DUK_DATE_FLAG_TIMESETTER + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30960 
30961 	/* 28: setMinutes */
30962 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30963 
30964 	/* 29: setUTCMinutes */
30965 	DUK_DATE_FLAG_TIMESETTER + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30966 
30967 	/* 30: setHours */
30968 	DUK_DATE_FLAG_TIMESETTER + DUK_DATE_FLAG_LOCALTIME + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
30969 
30970 	/* 31: setUTCHours */
30971 	DUK_DATE_FLAG_TIMESETTER + (4 << DUK_DATE_FLAG_VALUE_SHIFT),
30972 
30973 	/* 32: setDate */
30974 	DUK_DATE_FLAG_LOCALTIME + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30975 
30976 	/* 33: setUTCDate */
30977 	0 + (1 << DUK_DATE_FLAG_VALUE_SHIFT),
30978 
30979 	/* 34: setMonth */
30980 	DUK_DATE_FLAG_LOCALTIME + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30981 
30982 	/* 35: setUTCMonth */
30983 	0 + (2 << DUK_DATE_FLAG_VALUE_SHIFT),
30984 
30985 	/* 36: setFullYear */
30986 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_LOCALTIME + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30987 
30988 	/* 37: setUTCFullYear */
30989 	DUK_DATE_FLAG_NAN_TO_ZERO + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30990 
30991 	/* 38: getYear */
30992 	DUK_DATE_FLAG_LOCALTIME + DUK_DATE_FLAG_SUB1900 + (DUK_DATE_IDX_YEAR << DUK_DATE_FLAG_VALUE_SHIFT),
30993 
30994 	/* 39: setYear */
30995 	DUK_DATE_FLAG_NAN_TO_ZERO + DUK_DATE_FLAG_YEAR_FIXUP + (3 << DUK_DATE_FLAG_VALUE_SHIFT),
30996 };
30997 
duk__date_get_indirect_magic(duk_hthread * thr)30998 DUK_LOCAL duk_small_uint_t duk__date_get_indirect_magic(duk_hthread *thr) {
30999 	duk_small_uint_t magicidx = (duk_small_uint_t) duk_get_current_magic(thr);
31000 	DUK_ASSERT(magicidx < (duk_small_int_t) (sizeof(duk__date_magics) / sizeof(duk_uint16_t)));
31001 	return (duk_small_uint_t) duk__date_magics[magicidx];
31002 }
31003 
31004 #if defined(DUK_USE_DATE_BUILTIN)
31005 /*
31006  *  Constructor calls
31007  */
31008 
duk_bi_date_constructor(duk_hthread * thr)31009 DUK_INTERNAL duk_ret_t duk_bi_date_constructor(duk_hthread *thr) {
31010 	duk_idx_t nargs = duk_get_top(thr);
31011 	duk_bool_t is_cons = duk_is_constructor_call(thr);
31012 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31013 	duk_double_t d;
31014 
31015 	DUK_DDD(DUK_DDDPRINT("Date constructor, nargs=%ld, is_cons=%ld", (long) nargs, (long) is_cons));
31016 
31017 	(void) duk_push_object_helper(thr,
31018 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
31019 	                              DUK_HOBJECT_FLAG_FASTREFS |
31020 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DATE),
31021 	                              DUK_BIDX_DATE_PROTOTYPE);
31022 
31023 	/* Unlike most built-ins, the internal [[PrimitiveValue]] of a Date
31024 	 * is mutable.
31025 	 */
31026 
31027 	if (nargs == 0 || !is_cons) {
31028 		d = duk__timeclip(duk_time_get_ecmascript_time_nofrac(thr));
31029 		duk_push_number(thr, d);
31030 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31031 		if (!is_cons) {
31032 			/* called as a normal function: return new Date().toString() */
31033 			duk_to_string(thr, -1);
31034 		}
31035 		return 1;
31036 	} else if (nargs == 1) {
31037 		const char *str;
31038 		duk_to_primitive(thr, 0, DUK_HINT_NONE);
31039 		str = duk_get_string_notsymbol(thr, 0);
31040 		if (str) {
31041 			duk__parse_string(thr, str);
31042 			duk_replace(thr, 0);  /* may be NaN */
31043 		}
31044 		d = duk__timeclip(duk_to_number(thr, 0));  /* symbols fail here */
31045 		duk_push_number(thr, d);
31046 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_W);
31047 		return 1;
31048 	}
31049 
31050 	duk__set_parts_from_args(thr, dparts, nargs);
31051 
31052 	/* Parts are in local time, convert when setting. */
31053 
31054 	(void) duk__set_this_timeval_from_dparts(thr, dparts, DUK_DATE_FLAG_LOCALTIME /*flags*/);  /* -> [ ... this timeval ] */
31055 	duk_pop(thr);  /* -> [ ... this ] */
31056 	return 1;
31057 }
31058 
duk_bi_date_constructor_parse(duk_hthread * thr)31059 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_parse(duk_hthread *thr) {
31060 	return duk__parse_string(thr, duk_to_string(thr, 0));
31061 }
31062 
duk_bi_date_constructor_utc(duk_hthread * thr)31063 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_utc(duk_hthread *thr) {
31064 	duk_idx_t nargs = duk_get_top(thr);
31065 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31066 	duk_double_t d;
31067 
31068 	/* Behavior for nargs < 2 is implementation dependent: currently we'll
31069 	 * set a NaN time value (matching V8 behavior) in this case.
31070 	 */
31071 
31072 	if (nargs < 2) {
31073 		duk_push_nan(thr);
31074 	} else {
31075 		duk__set_parts_from_args(thr, dparts, nargs);
31076 		d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31077 		duk_push_number(thr, d);
31078 	}
31079 	return 1;
31080 }
31081 
duk_bi_date_constructor_now(duk_hthread * thr)31082 DUK_INTERNAL duk_ret_t duk_bi_date_constructor_now(duk_hthread *thr) {
31083 	duk_double_t d;
31084 
31085 	d = duk_time_get_ecmascript_time_nofrac(thr);
31086 	DUK_ASSERT(duk__timeclip(d) == d);  /* TimeClip() should never be necessary */
31087 	duk_push_number(thr, d);
31088 	return 1;
31089 }
31090 
31091 /*
31092  *  String/JSON conversions
31093  *
31094  *  Human readable conversions are now basically ISO 8601 with a space
31095  *  (instead of 'T') as the date/time separator.  This is a good baseline
31096  *  and is platform independent.
31097  *
31098  *  A shared native helper to provide many conversions.  Magic value contains
31099  *  a set of flags.  The helper provides:
31100  *
31101  *    toString()
31102  *    toDateString()
31103  *    toTimeString()
31104  *    toLocaleString()
31105  *    toLocaleDateString()
31106  *    toLocaleTimeString()
31107  *    toUTCString()
31108  *    toISOString()
31109  *
31110  *  Notes:
31111  *
31112  *    - Date.prototype.toGMTString() and Date.prototype.toUTCString() are
31113  *      required to be the same ECMAScript function object (!), so it is
31114  *      omitted from here.
31115  *
31116  *    - Date.prototype.toUTCString(): E5.1 specification does not require a
31117  *      specific format, but result should be human readable.  The
31118  *      specification suggests using ISO 8601 format with a space (instead
31119  *      of 'T') separator if a more human readable format is not available.
31120  *
31121  *    - Date.prototype.toISOString(): unlike other conversion functions,
31122  *      toISOString() requires a RangeError for invalid date values.
31123  */
31124 
duk_bi_date_prototype_tostring_shared(duk_hthread * thr)31125 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_tostring_shared(duk_hthread *thr) {
31126 	duk_small_uint_t flags = duk__date_get_indirect_magic(thr);
31127 	return duk__to_string_helper(thr, flags);
31128 }
31129 
duk_bi_date_prototype_value_of(duk_hthread * thr)31130 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_value_of(duk_hthread *thr) {
31131 	/* This native function is also used for Date.prototype.getTime()
31132 	 * as their behavior is identical.
31133 	 */
31134 
31135 	duk_double_t d = duk__push_this_get_timeval(thr, 0 /*flags*/);  /* -> [ this ] */
31136 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31137 	duk_push_number(thr, d);
31138 	return 1;
31139 }
31140 
duk_bi_date_prototype_to_json(duk_hthread * thr)31141 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_to_json(duk_hthread *thr) {
31142 	/* Note: toJSON() is a generic function which works even if 'this'
31143 	 * is not a Date.  The sole argument is ignored.
31144 	 */
31145 
31146 	duk_push_this(thr);
31147 	duk_to_object(thr, -1);
31148 
31149 	duk_dup_top(thr);
31150 	duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
31151 	if (duk_is_number(thr, -1)) {
31152 		duk_double_t d = duk_get_number(thr, -1);
31153 		if (!DUK_ISFINITE(d)) {
31154 			duk_push_null(thr);
31155 			return 1;
31156 		}
31157 	}
31158 	duk_pop(thr);
31159 
31160 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_ISO_STRING);
31161 	duk_dup_m2(thr);  /* -> [ O toIsoString O ] */
31162 	duk_call_method(thr, 0);
31163 	return 1;
31164 }
31165 
31166 /*
31167  *  Getters.
31168  *
31169  *  Implementing getters is quite easy.  The internal time value is either
31170  *  NaN, or represents milliseconds (without fractions) from Jan 1, 1970.
31171  *  The internal time value can be converted to integer parts, and each
31172  *  part will be normalized and will fit into a 32-bit signed integer.
31173  *
31174  *  A shared native helper to provide all getters.  Magic value contains
31175  *  a set of flags and also packs the date component index argument.  The
31176  *  helper provides:
31177  *
31178  *    getFullYear()
31179  *    getUTCFullYear()
31180  *    getMonth()
31181  *    getUTCMonth()
31182  *    getDate()
31183  *    getUTCDate()
31184  *    getDay()
31185  *    getUTCDay()
31186  *    getHours()
31187  *    getUTCHours()
31188  *    getMinutes()
31189  *    getUTCMinutes()
31190  *    getSeconds()
31191  *    getUTCSeconds()
31192  *    getMilliseconds()
31193  *    getUTCMilliseconds()
31194  *    getYear()
31195  *
31196  *  Notes:
31197  *
31198  *    - Date.prototype.getDate(): 'date' means day-of-month, and is
31199  *      zero-based in internal calculations but public API expects it to
31200  *      be one-based.
31201  *
31202  *    - Date.prototype.getTime() and Date.prototype.valueOf() have identical
31203  *      behavior.  They have separate function objects, but share the same C
31204  *      function (duk_bi_date_prototype_value_of).
31205  */
31206 
duk_bi_date_prototype_get_shared(duk_hthread * thr)31207 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_shared(duk_hthread *thr) {
31208 	duk_small_uint_t flags_and_idx = duk__date_get_indirect_magic(thr);
31209 	return duk__get_part_helper(thr, flags_and_idx);
31210 }
31211 
duk_bi_date_prototype_get_timezone_offset(duk_hthread * thr)31212 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_get_timezone_offset(duk_hthread *thr) {
31213 	/*
31214 	 *  Return (t - LocalTime(t)) in minutes:
31215 	 *
31216 	 *    t - LocalTime(t) = t - (t + LocalTZA + DaylightSavingTA(t))
31217 	 *                     = -(LocalTZA + DaylightSavingTA(t))
31218 	 *
31219 	 *  where DaylightSavingTA() is checked for time 't'.
31220 	 *
31221 	 *  Note that the sign of the result is opposite to common usage,
31222 	 *  e.g. for EE(S)T which normally is +2h or +3h from UTC, this
31223 	 *  function returns -120 or -180.
31224 	 *
31225 	 */
31226 
31227 	duk_double_t d;
31228 	duk_int_t tzoffset;
31229 
31230 	/* Note: DST adjustment is determined using UTC time. */
31231 	d = duk__push_this_get_timeval(thr, 0 /*flags*/);
31232 	DUK_ASSERT(DUK_ISFINITE(d) || DUK_ISNAN(d));
31233 	if (DUK_ISNAN(d)) {
31234 		duk_push_nan(thr);
31235 	} else {
31236 		DUK_ASSERT(DUK_ISFINITE(d));
31237 		tzoffset = DUK_USE_DATE_GET_LOCAL_TZOFFSET(d);
31238 		duk_push_int(thr, -tzoffset / 60);
31239 	}
31240 	return 1;
31241 }
31242 
31243 /*
31244  *  Setters.
31245  *
31246  *  Setters are a bit more complicated than getters.  Component setters
31247  *  break down the current time value into its (normalized) component
31248  *  parts, replace one or more components with -unnormalized- new values,
31249  *  and the components are then converted back into a time value.  As an
31250  *  example of using unnormalized values:
31251  *
31252  *    var d = new Date(1234567890);
31253  *
31254  *  is equivalent to:
31255  *
31256  *    var d = new Date(0);
31257  *    d.setUTCMilliseconds(1234567890);
31258  *
31259  *  A shared native helper to provide almost all setters.  Magic value
31260  *  contains a set of flags and also packs the "maxnargs" argument.  The
31261  *  helper provides:
31262  *
31263  *    setMilliseconds()
31264  *    setUTCMilliseconds()
31265  *    setSeconds()
31266  *    setUTCSeconds()
31267  *    setMinutes()
31268  *    setUTCMinutes()
31269  *    setHours()
31270  *    setUTCHours()
31271  *    setDate()
31272  *    setUTCDate()
31273  *    setMonth()
31274  *    setUTCMonth()
31275  *    setFullYear()
31276  *    setUTCFullYear()
31277  *    setYear()
31278  *
31279  *  Notes:
31280  *
31281  *    - Date.prototype.setYear() (Section B addition): special year check
31282  *      is omitted.  NaN / Infinity will just flow through and ultimately
31283  *      result in a NaN internal time value.
31284  *
31285  *    - Date.prototype.setYear() does not have optional arguments for
31286  *      setting month and day-in-month (like setFullYear()), but we indicate
31287  *      'maxnargs' to be 3 to get the year written to the correct component
31288  *      index in duk__set_part_helper().  The function has nargs == 1, so only
31289  *      the year will be set regardless of actual argument count.
31290  */
31291 
duk_bi_date_prototype_set_shared(duk_hthread * thr)31292 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_shared(duk_hthread *thr) {
31293 	duk_small_uint_t flags_and_maxnargs = duk__date_get_indirect_magic(thr);
31294 	return duk__set_part_helper(thr, flags_and_maxnargs);
31295 }
31296 
duk_bi_date_prototype_set_time(duk_hthread * thr)31297 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_set_time(duk_hthread *thr) {
31298 	duk_double_t d;
31299 
31300 	(void) duk__push_this_get_timeval(thr, 0 /*flags*/); /* -> [ timeval this ] */
31301 	d = duk__timeclip(duk_to_number(thr, 0));
31302 	duk_push_number(thr, d);
31303 	duk_dup_top(thr);
31304 	duk_put_prop_stridx_short(thr, -3, DUK_STRIDX_INT_VALUE); /* -> [ timeval this timeval ] */
31305 
31306 	return 1;
31307 }
31308 
31309 /*
31310  *  Misc.
31311  */
31312 
31313 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_date_prototype_toprimitive(duk_hthread * thr)31314 DUK_INTERNAL duk_ret_t duk_bi_date_prototype_toprimitive(duk_hthread *thr) {
31315 	duk_size_t hintlen;
31316 	const char *hintstr;
31317 	duk_int_t hint;
31318 
31319 	/* Invokes OrdinaryToPrimitive() with suitable hint.  Note that the
31320 	 * method is generic, and works on non-Date arguments too.
31321 	 *
31322 	 * https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype-@@toprimitive
31323 	 */
31324 
31325 	duk_push_this(thr);
31326 	duk_require_object(thr, -1);
31327 	DUK_ASSERT_TOP(thr, 2);
31328 
31329 	hintstr = duk_require_lstring(thr, 0, &hintlen);
31330 	if ((hintlen == 6 && DUK_STRCMP(hintstr, "string") == 0) ||
31331 	    (hintlen == 7 && DUK_STRCMP(hintstr, "default") == 0)) {
31332 		hint = DUK_HINT_STRING;
31333 	} else if (hintlen == 6 && DUK_STRCMP(hintstr, "number") == 0) {
31334 		hint = DUK_HINT_NUMBER;
31335 	} else {
31336 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
31337 	}
31338 
31339 	duk_to_primitive_ordinary(thr, -1, hint);
31340 	return 1;
31341 }
31342 #endif  /* DUK_USE_SYMBOL_BUILTIN */
31343 
31344 #endif  /* DUK_USE_DATE_BUILTIN */
31345 
31346 /* automatic undefs */
31347 #undef DUK__CF_ACCEPT
31348 #undef DUK__CF_ACCEPT_NUL
31349 #undef DUK__CF_NEG
31350 #undef DUK__DPRINT_DPARTS
31351 #undef DUK__DPRINT_PARTS
31352 #undef DUK__DPRINT_PARTS_AND_DPARTS
31353 #undef DUK__LOCAL_TZOFFSET_MAXITER
31354 #undef DUK__NUM_ISO8601_PARSER_PARTS
31355 #undef DUK__PACK_RULE
31356 #undef DUK__PI_DAY
31357 #undef DUK__PI_HOUR
31358 #undef DUK__PI_MILLISECOND
31359 #undef DUK__PI_MINUTE
31360 #undef DUK__PI_MONTH
31361 #undef DUK__PI_SECOND
31362 #undef DUK__PI_TZHOUR
31363 #undef DUK__PI_TZMINUTE
31364 #undef DUK__PI_YEAR
31365 #undef DUK__PM_DAY
31366 #undef DUK__PM_HOUR
31367 #undef DUK__PM_MILLISECOND
31368 #undef DUK__PM_MINUTE
31369 #undef DUK__PM_MONTH
31370 #undef DUK__PM_SECOND
31371 #undef DUK__PM_TZHOUR
31372 #undef DUK__PM_TZMINUTE
31373 #undef DUK__PM_YEAR
31374 #undef DUK__RULE_MASK_PART_SEP
31375 #undef DUK__SI_COLON
31376 #undef DUK__SI_MINUS
31377 #undef DUK__SI_NUL
31378 #undef DUK__SI_PERIOD
31379 #undef DUK__SI_PLUS
31380 #undef DUK__SI_SPACE
31381 #undef DUK__SI_T
31382 #undef DUK__SI_Z
31383 #undef DUK__SM_COLON
31384 #undef DUK__SM_MINUS
31385 #undef DUK__SM_NUL
31386 #undef DUK__SM_PERIOD
31387 #undef DUK__SM_PLUS
31388 #undef DUK__SM_SPACE
31389 #undef DUK__SM_T
31390 #undef DUK__SM_Z
31391 #undef DUK__UNPACK_RULE
31392 #undef DUK__WEEKDAY_MOD_ADDER
31393 #undef DUK__YEAR
31394 #line 1 "duk_bi_date_unix.c"
31395 /*
31396  *  Unix-like Date providers
31397  *
31398  *  Generally useful Unix / POSIX / ANSI Date providers.
31399  */
31400 
31401 /* #include duk_internal.h -> already included */
31402 
31403 /* The necessary #includes are in place in duk_config.h. */
31404 
31405 /* Buffer sizes for some UNIX calls.  Larger than strictly necessary
31406  * to avoid Valgrind errors.
31407  */
31408 #define DUK__STRPTIME_BUF_SIZE  64
31409 #define DUK__STRFTIME_BUF_SIZE  64
31410 
31411 #if defined(DUK_USE_DATE_NOW_GETTIMEOFDAY)
31412 /* Get current ECMAScript time (= UNIX/Posix time, but in milliseconds). */
duk_bi_date_get_now_gettimeofday(void)31413 DUK_INTERNAL duk_double_t duk_bi_date_get_now_gettimeofday(void) {
31414 	struct timeval tv;
31415 	duk_double_t d;
31416 
31417 	if (gettimeofday(&tv, NULL) != 0) {
31418 		DUK_D(DUK_DPRINT("gettimeofday() failed"));
31419 		return 0.0;
31420 	}
31421 
31422 	/* As of Duktape 2.2.0 allow fractions. */
31423 	d = ((duk_double_t) tv.tv_sec) * 1000.0 +
31424 	    ((duk_double_t) tv.tv_usec) / 1000.0;
31425 
31426 	return d;
31427 }
31428 #endif  /* DUK_USE_DATE_NOW_GETTIMEOFDAY */
31429 
31430 #if defined(DUK_USE_DATE_NOW_TIME)
31431 /* Not a very good provider: only full seconds are available. */
duk_bi_date_get_now_time(void)31432 DUK_INTERNAL duk_double_t duk_bi_date_get_now_time(void) {
31433 	time_t t;
31434 
31435 	t = time(NULL);
31436 	if (t == (time_t) -1) {
31437 		DUK_D(DUK_DPRINT("time() failed"));
31438 		return 0.0;
31439 	}
31440 	return ((duk_double_t) t) * 1000.0;
31441 }
31442 #endif  /* DUK_USE_DATE_NOW_TIME */
31443 
31444 #if defined(DUK_USE_DATE_TZO_GMTIME) || defined(DUK_USE_DATE_TZO_GMTIME_R) || defined(DUK_USE_DATE_TZO_GMTIME_S)
31445 /* Get local time offset (in seconds) for a certain (UTC) instant 'd'. */
duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d)31446 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_gmtime(duk_double_t d) {
31447 	time_t t, t1, t2;
31448 	duk_int_t parts[DUK_DATE_IDX_NUM_PARTS];
31449 	duk_double_t dparts[DUK_DATE_IDX_NUM_PARTS];
31450 	struct tm tms[2];
31451 #if defined(DUK_USE_DATE_TZO_GMTIME)
31452 	struct tm *tm_ptr;
31453 #endif
31454 
31455 	/* For NaN/inf, the return value doesn't matter. */
31456 	if (!DUK_ISFINITE(d)) {
31457 		return 0;
31458 	}
31459 
31460 	/* If not within ECMAScript range, some integer time calculations
31461 	 * won't work correctly (and some asserts will fail), so bail out
31462 	 * if so.  This fixes test-bug-date-insane-setyear.js.  There is
31463 	 * a +/- 24h leeway in this range check to avoid a test262 corner
31464 	 * case documented in test-bug-date-timeval-edges.js.
31465 	 */
31466 	if (!duk_bi_date_timeval_in_leeway_range(d)) {
31467 		DUK_DD(DUK_DDPRINT("timeval not within valid range, skip tzoffset computation to avoid integer overflows"));
31468 		return 0;
31469 	}
31470 
31471 	/*
31472 	 *  This is a bit tricky to implement portably.  The result depends
31473 	 *  on the timestamp (specifically, DST depends on the timestamp).
31474 	 *  If e.g. UNIX APIs are used, they'll have portability issues with
31475 	 *  very small and very large years.
31476 	 *
31477 	 *  Current approach:
31478 	 *
31479 	 *  - Stay within portable UNIX limits by using equivalent year mapping.
31480 	 *    Avoid year 1970 and 2038 as some conversions start to fail, at
31481 	 *    least on some platforms.  Avoiding 1970 means that there are
31482 	 *    currently DST discrepancies for 1970.
31483 	 *
31484 	 *  - Create a UTC and local time breakdowns from 't'.  Then create
31485 	 *    a time_t using gmtime() and localtime() and compute the time
31486 	 *    difference between the two.
31487 	 *
31488 	 *  Equivalent year mapping (E5 Section 15.9.1.8):
31489 	 *
31490 	 *    If the host environment provides functionality for determining
31491 	 *    daylight saving time, the implementation of ECMAScript is free
31492 	 *    to map the year in question to an equivalent year (same
31493 	 *    leap-year-ness and same starting week day for the year) for which
31494 	 *    the host environment provides daylight saving time information.
31495 	 *    The only restriction is that all equivalent years should produce
31496 	 *    the same result.
31497 	 *
31498 	 *  This approach is quite reasonable but not entirely correct, e.g.
31499 	 *  the specification also states (E5 Section 15.9.1.8):
31500 	 *
31501 	 *    The implementation of ECMAScript should not try to determine
31502 	 *    whether the exact time was subject to daylight saving time, but
31503 	 *    just whether daylight saving time would have been in effect if
31504 	 *    the _current daylight saving time algorithm_ had been used at the
31505 	 *    time.  This avoids complications such as taking into account the
31506 	 *    years that the locale observed daylight saving time year round.
31507 	 *
31508 	 *  Since we rely on the platform APIs for conversions between local
31509 	 *  time and UTC, we can't guarantee the above.  Rather, if the platform
31510 	 *  has historical DST rules they will be applied.  This seems to be the
31511 	 *  general preferred direction in ECMAScript standardization (or at least
31512 	 *  implementations) anyway, and even the equivalent year mapping should
31513 	 *  be disabled if the platform is known to handle DST properly for the
31514 	 *  full ECMAScript range.
31515 	 *
31516 	 *  The following has useful discussion and links:
31517 	 *
31518 	 *    https://bugzilla.mozilla.org/show_bug.cgi?id=351066
31519 	 */
31520 
31521 	duk_bi_date_timeval_to_parts(d, parts, dparts, DUK_DATE_FLAG_EQUIVYEAR /*flags*/);
31522 	DUK_ASSERT(parts[DUK_DATE_IDX_YEAR] >= 1970 && parts[DUK_DATE_IDX_YEAR] <= 2038);
31523 
31524 	d = duk_bi_date_get_timeval_from_dparts(dparts, 0 /*flags*/);
31525 	DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0);  /* unsigned 31-bit range */
31526 	t = (time_t) (d / 1000.0);
31527 	DUK_DDD(DUK_DDDPRINT("timeval: %lf -> time_t %ld", (double) d, (long) t));
31528 
31529 	duk_memzero((void *) tms, sizeof(struct tm) * 2);
31530 
31531 #if defined(DUK_USE_DATE_TZO_GMTIME_R)
31532 	(void) gmtime_r(&t, &tms[0]);
31533 	(void) localtime_r(&t, &tms[1]);
31534 #elif defined(DUK_USE_DATE_TZO_GMTIME_S)
31535 	(void) gmtime_s(&t, &tms[0]);
31536 	(void) localtime_s(&t, &tms[1]);
31537 #elif defined(DUK_USE_DATE_TZO_GMTIME)
31538 	tm_ptr = gmtime(&t);
31539 	duk_memcpy((void *) &tms[0], tm_ptr, sizeof(struct tm));
31540 	tm_ptr = localtime(&t);
31541 	duk_memcpy((void *) &tms[1], tm_ptr, sizeof(struct tm));
31542 #else
31543 #error internal error
31544 #endif
31545 	DUK_DDD(DUK_DDDPRINT("gmtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31546 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31547 	                     (long) tms[0].tm_sec, (long) tms[0].tm_min, (long) tms[0].tm_hour,
31548 	                     (long) tms[0].tm_mday, (long) tms[0].tm_mon, (long) tms[0].tm_year,
31549 	                     (long) tms[0].tm_wday, (long) tms[0].tm_yday, (long) tms[0].tm_isdst));
31550 	DUK_DDD(DUK_DDDPRINT("localtime result: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31551 	                     "wday:%ld,yday:%ld,isdst:%ld}",
31552 	                     (long) tms[1].tm_sec, (long) tms[1].tm_min, (long) tms[1].tm_hour,
31553 	                     (long) tms[1].tm_mday, (long) tms[1].tm_mon, (long) tms[1].tm_year,
31554 	                     (long) tms[1].tm_wday, (long) tms[1].tm_yday, (long) tms[1].tm_isdst));
31555 
31556 	/* tm_isdst is both an input and an output to mktime(), use 0 to
31557 	 * avoid DST handling in mktime():
31558 	 * - https://github.com/svaarala/duktape/issues/406
31559 	 * - http://stackoverflow.com/questions/8558919/mktime-and-tm-isdst
31560 	 */
31561 	tms[0].tm_isdst = 0;
31562 	tms[1].tm_isdst = 0;
31563 	t1 = mktime(&tms[0]);  /* UTC */
31564 	t2 = mktime(&tms[1]);  /* local */
31565 	if (t1 == (time_t) -1 || t2 == (time_t) -1) {
31566 		/* This check used to be for (t < 0) but on some platforms
31567 		 * time_t is unsigned and apparently the proper way to detect
31568 		 * an mktime() error return is the cast above.  See e.g.:
31569 		 * http://pubs.opengroup.org/onlinepubs/009695299/functions/mktime.html
31570 		 */
31571 		goto mktime_error;
31572 	}
31573 	DUK_DDD(DUK_DDDPRINT("t1=%ld (utc), t2=%ld (local)", (long) t1, (long) t2));
31574 
31575 	/* Compute final offset in seconds, positive if local time ahead of
31576 	 * UTC (returned value is UTC-to-local offset).
31577 	 *
31578 	 * difftime() returns a double, so coercion to int generates quite
31579 	 * a lot of code.  Direct subtraction is not portable, however.
31580 	 * XXX: allow direct subtraction on known platforms.
31581 	 */
31582 #if 0
31583 	return (duk_int_t) (t2 - t1);
31584 #endif
31585 	return (duk_int_t) difftime(t2, t1);
31586 
31587  mktime_error:
31588 	/* XXX: return something more useful, so that caller can throw? */
31589 	DUK_D(DUK_DPRINT("mktime() failed, d=%lf", (double) d));
31590 	return 0;
31591 }
31592 #endif  /* DUK_USE_DATE_TZO_GMTIME */
31593 
31594 #if defined(DUK_USE_DATE_PRS_STRPTIME)
duk_bi_date_parse_string_strptime(duk_hthread * thr,const char * str)31595 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_strptime(duk_hthread *thr, const char *str) {
31596 	struct tm tm;
31597 	time_t t;
31598 	char buf[DUK__STRPTIME_BUF_SIZE];
31599 
31600 	/* Copy to buffer with slack to avoid Valgrind gripes from strptime. */
31601 	DUK_ASSERT(str != NULL);
31602 	duk_memzero(buf, sizeof(buf));  /* valgrind whine without this */
31603 	DUK_SNPRINTF(buf, sizeof(buf), "%s", (const char *) str);
31604 	buf[sizeof(buf) - 1] = (char) 0;
31605 
31606 	DUK_DDD(DUK_DDDPRINT("parsing: '%s'", (const char *) buf));
31607 
31608 	duk_memzero(&tm, sizeof(tm));
31609 	if (strptime((const char *) buf, "%c", &tm) != NULL) {
31610 		DUK_DDD(DUK_DDDPRINT("before mktime: tm={sec:%ld,min:%ld,hour:%ld,mday:%ld,mon:%ld,year:%ld,"
31611 		                     "wday:%ld,yday:%ld,isdst:%ld}",
31612 		                     (long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
31613 		                     (long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
31614 		                     (long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
31615 		tm.tm_isdst = -1;  /* negative: dst info not available */
31616 
31617 		t = mktime(&tm);
31618 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31619 		if (t >= 0) {
31620 			duk_push_number(thr, ((duk_double_t) t) * 1000.0);
31621 			return 1;
31622 		}
31623 	}
31624 
31625 	return 0;
31626 }
31627 #endif  /* DUK_USE_DATE_PRS_STRPTIME */
31628 
31629 #if defined(DUK_USE_DATE_PRS_GETDATE)
duk_bi_date_parse_string_getdate(duk_hthread * thr,const char * str)31630 DUK_INTERNAL duk_bool_t duk_bi_date_parse_string_getdate(duk_hthread *thr, const char *str) {
31631 	struct tm tm;
31632 	duk_small_int_t rc;
31633 	time_t t;
31634 
31635 	/* For this to work, DATEMSK must be set, so this is not very
31636 	 * convenient for an embeddable interpreter.
31637 	 */
31638 
31639 	duk_memzero(&tm, sizeof(struct tm));
31640 	rc = (duk_small_int_t) getdate_r(str, &tm);
31641 	DUK_DDD(DUK_DDDPRINT("getdate_r() -> %ld", (long) rc));
31642 
31643 	if (rc == 0) {
31644 		t = mktime(&tm);
31645 		DUK_DDD(DUK_DDDPRINT("mktime() -> %ld", (long) t));
31646 		if (t >= 0) {
31647 			duk_push_number(thr, (duk_double_t) t);
31648 			return 1;
31649 		}
31650 	}
31651 
31652 	return 0;
31653 }
31654 #endif  /* DUK_USE_DATE_PRS_GETDATE */
31655 
31656 #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)31657 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) {
31658 	char buf[DUK__STRFTIME_BUF_SIZE];
31659 	struct tm tm;
31660 	const char *fmt;
31661 
31662 	DUK_UNREF(tzoffset);
31663 
31664 	/* If the platform doesn't support the entire ECMAScript range, we need
31665 	 * to return 0 so that the caller can fall back to the default formatter.
31666 	 *
31667 	 * For now, assume that if time_t is 8 bytes or more, the whole ECMAScript
31668 	 * range is supported.  For smaller time_t values (4 bytes in practice),
31669 	 * assumes that the signed 32-bit range is supported.
31670 	 *
31671 	 * XXX: detect this more correctly per platform.  The size of time_t is
31672 	 * probably not an accurate guarantee of strftime() supporting or not
31673 	 * supporting a large time range (the full ECMAScript range).
31674 	 */
31675 	if (sizeof(time_t) < 8 &&
31676 	    (parts[DUK_DATE_IDX_YEAR] < 1970 || parts[DUK_DATE_IDX_YEAR] > 2037)) {
31677 		/* be paranoid for 32-bit time values (even avoiding negative ones) */
31678 		return 0;
31679 	}
31680 
31681 	duk_memzero(&tm, sizeof(tm));
31682 	tm.tm_sec = parts[DUK_DATE_IDX_SECOND];
31683 	tm.tm_min = parts[DUK_DATE_IDX_MINUTE];
31684 	tm.tm_hour = parts[DUK_DATE_IDX_HOUR];
31685 	tm.tm_mday = parts[DUK_DATE_IDX_DAY];       /* already one-based */
31686 	tm.tm_mon = parts[DUK_DATE_IDX_MONTH] - 1;  /* one-based -> zero-based */
31687 	tm.tm_year = parts[DUK_DATE_IDX_YEAR] - 1900;
31688 	tm.tm_wday = parts[DUK_DATE_IDX_WEEKDAY];
31689 	tm.tm_isdst = 0;
31690 
31691 	duk_memzero(buf, sizeof(buf));
31692 	if ((flags & DUK_DATE_FLAG_TOSTRING_DATE) && (flags & DUK_DATE_FLAG_TOSTRING_TIME)) {
31693 		fmt = "%c";
31694 	} else if (flags & DUK_DATE_FLAG_TOSTRING_DATE) {
31695 		fmt = "%x";
31696 	} else {
31697 		DUK_ASSERT(flags & DUK_DATE_FLAG_TOSTRING_TIME);
31698 		fmt = "%X";
31699 	}
31700 	(void) strftime(buf, sizeof(buf) - 1, fmt, &tm);
31701 	DUK_ASSERT(buf[sizeof(buf) - 1] == 0);
31702 
31703 	duk_push_string(thr, buf);
31704 	return 1;
31705 }
31706 #endif  /* DUK_USE_DATE_FMT_STRFTIME */
31707 
31708 #if defined(DUK_USE_GET_MONOTONIC_TIME_CLOCK_GETTIME)
duk_bi_date_get_monotonic_time_clock_gettime(void)31709 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_clock_gettime(void) {
31710 	struct timespec ts;
31711 
31712 	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
31713 		return (duk_double_t) ts.tv_sec * 1000.0 + (duk_double_t) ts.tv_nsec / 1000000.0;
31714 	} else {
31715 		DUK_D(DUK_DPRINT("clock_gettime(CLOCK_MONOTONIC) failed"));
31716 		return 0.0;
31717 	}
31718 }
31719 #endif
31720 
31721 /* automatic undefs */
31722 #undef DUK__STRFTIME_BUF_SIZE
31723 #undef DUK__STRPTIME_BUF_SIZE
31724 #line 1 "duk_bi_date_windows.c"
31725 /*
31726  *  Windows Date providers
31727  *
31728  *  Platform specific links:
31729  *
31730  *    - http://msdn.microsoft.com/en-us/library/windows/desktop/ms725473(v=vs.85).aspx
31731  */
31732 
31733 /* #include duk_internal.h -> already included */
31734 
31735 /* The necessary #includes are in place in duk_config.h. */
31736 
31737 #if defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS)
31738 /* Shared Windows helpers. */
duk__convert_systime_to_ularge(const SYSTEMTIME * st,ULARGE_INTEGER * res)31739 DUK_LOCAL void duk__convert_systime_to_ularge(const SYSTEMTIME *st, ULARGE_INTEGER *res) {
31740 	FILETIME ft;
31741 	if (SystemTimeToFileTime(st, &ft) == 0) {
31742 		DUK_D(DUK_DPRINT("SystemTimeToFileTime() failed, returning 0"));
31743 		res->QuadPart = 0;
31744 	} else {
31745 		res->LowPart = ft.dwLowDateTime;
31746 		res->HighPart = ft.dwHighDateTime;
31747 	}
31748 }
31749 
31750 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk__convert_filetime_to_ularge(const FILETIME * ft,ULARGE_INTEGER * res)31751 DUK_LOCAL void duk__convert_filetime_to_ularge(const FILETIME *ft, ULARGE_INTEGER *res) {
31752 	res->LowPart = ft->dwLowDateTime;
31753 	res->HighPart = ft->dwHighDateTime;
31754 }
31755 #endif  /* DUK_USE_DATE_NOW_WINDOWS_SUBMS */
31756 
duk__set_systime_jan1970(SYSTEMTIME * st)31757 DUK_LOCAL void duk__set_systime_jan1970(SYSTEMTIME *st) {
31758 	duk_memzero((void *) st, sizeof(*st));
31759 	st->wYear = 1970;
31760 	st->wMonth = 1;
31761 	st->wDayOfWeek = 4;  /* not sure whether or not needed; Thursday */
31762 	st->wDay = 1;
31763 	DUK_ASSERT(st->wHour == 0);
31764 	DUK_ASSERT(st->wMinute == 0);
31765 	DUK_ASSERT(st->wSecond == 0);
31766 	DUK_ASSERT(st->wMilliseconds == 0);
31767 }
31768 #endif  /* defined(DUK_USE_DATE_NOW_WINDOWS) || defined(DUK_USE_DATE_TZO_WINDOWS) */
31769 
31770 #if defined(DUK_USE_DATE_NOW_WINDOWS)
duk_bi_date_get_now_windows(void)31771 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows(void) {
31772 	/* Suggested step-by-step method from documentation of RtlTimeToSecondsSince1970:
31773 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724928(v=vs.85).aspx
31774 	 */
31775 	SYSTEMTIME st1, st2;
31776 	ULARGE_INTEGER tmp1, tmp2;
31777 
31778 	GetSystemTime(&st1);
31779 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31780 
31781 	duk__set_systime_jan1970(&st2);
31782 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31783 
31784 	/* Difference is in 100ns units, convert to milliseconds, keeping
31785 	 * fractions since Duktape 2.2.0.  This is only theoretical because
31786 	 * SYSTEMTIME is limited to milliseconds.
31787 	 */
31788 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31789 }
31790 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31791 
31792 #if defined(DUK_USE_DATE_NOW_WINDOWS_SUBMS)
duk_bi_date_get_now_windows_subms(void)31793 DUK_INTERNAL duk_double_t duk_bi_date_get_now_windows_subms(void) {
31794 	/* Variant of the basic algorithm using GetSystemTimePreciseAsFileTime()
31795 	 * for more accuracy.
31796 	 */
31797 	FILETIME ft1;
31798 	SYSTEMTIME st2;
31799 	ULARGE_INTEGER tmp1, tmp2;
31800 
31801 	GetSystemTimePreciseAsFileTime(&ft1);
31802 	duk__convert_filetime_to_ularge((const FILETIME *) &ft1, &tmp1);
31803 
31804 	duk__set_systime_jan1970(&st2);
31805 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31806 
31807 	/* Difference is in 100ns units, convert to milliseconds, keeping
31808 	 * fractions since Duktape 2.2.0.
31809 	 */
31810 	return (duk_double_t) ((LONGLONG) tmp1.QuadPart - (LONGLONG) tmp2.QuadPart) / 10000.0;
31811 }
31812 #endif  /* DUK_USE_DATE_NOW_WINDOWS */
31813 
31814 #if defined(DUK_USE_DATE_TZO_WINDOWS)
duk_bi_date_get_local_tzoffset_windows(duk_double_t d)31815 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows(duk_double_t d) {
31816 	SYSTEMTIME st1;
31817 	SYSTEMTIME st2;
31818 	SYSTEMTIME st3;
31819 	ULARGE_INTEGER tmp1;
31820 	ULARGE_INTEGER tmp2;
31821 	ULARGE_INTEGER tmp3;
31822 	FILETIME ft1;
31823 	BOOL ret;
31824 
31825 	/* XXX: handling of timestamps outside Windows supported range.
31826 	 * How does Windows deal with dates before 1600?  Does windows
31827 	 * support all ECMAScript years (like -200000 and +200000)?
31828 	 * Should equivalent year mapping be used here too?  If so, use
31829 	 * a shared helper (currently integrated into timeval-to-parts).
31830 	 */
31831 
31832 	/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
31833 	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
31834 	 */
31835 
31836 	duk__set_systime_jan1970(&st1);
31837 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31838 	tmp2.QuadPart = (ULONGLONG) (d * 10000.0);  /* millisec -> 100ns units since jan 1, 1970 */
31839 	tmp2.QuadPart += tmp1.QuadPart;             /* input 'd' in Windows UTC, 100ns units */
31840 
31841 	ft1.dwLowDateTime = tmp2.LowPart;
31842 	ft1.dwHighDateTime = tmp2.HighPart;
31843 	ret = FileTimeToSystemTime((const FILETIME *) &ft1, &st2);
31844 	if (!ret) {
31845 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
31846 		return 0;
31847 	}
31848 	if (SystemTimeToTzSpecificLocalTime((LPTIME_ZONE_INFORMATION) NULL, &st2, &st3) == 0) {
31849 		DUK_D(DUK_DPRINT("SystemTimeToTzSpecificLocalTime() failed, return tzoffset 0"));
31850 		return 0;
31851 	}
31852 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st3, &tmp3);
31853 
31854 	/* Positive if local time ahead of UTC. */
31855 	return (duk_int_t) (((LONGLONG) tmp3.QuadPart - (LONGLONG) tmp2.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
31856 }
31857 #endif  /* DUK_USE_DATE_TZO_WINDOWS */
31858 
31859 #if defined(DUK_USE_DATE_TZO_WINDOWS_NO_DST)
duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d)31860 DUK_INTERNAL duk_int_t duk_bi_date_get_local_tzoffset_windows_no_dst(duk_double_t d) {
31861 	SYSTEMTIME st1;
31862 	SYSTEMTIME st2;
31863 	FILETIME ft1;
31864 	FILETIME ft2;
31865 	ULARGE_INTEGER tmp1;
31866 	ULARGE_INTEGER tmp2;
31867 	BOOL ret;
31868 
31869 	/* Do a similar computation to duk_bi_date_get_local_tzoffset_windows
31870 	 * but without accounting for daylight savings time.  Use this on
31871 	 * Windows platforms (like Durango) that don't support the
31872 	 * SystemTimeToTzSpecificLocalTime() call.
31873 	 */
31874 
31875 	/* current time not needed for this computation */
31876 	DUK_UNREF(d);
31877 
31878 	duk__set_systime_jan1970(&st1);
31879 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st1, &tmp1);
31880 
31881 	ft1.dwLowDateTime = tmp1.LowPart;
31882 	ft1.dwHighDateTime = tmp1.HighPart;
31883 	ret = FileTimeToLocalFileTime((const FILETIME *) &ft1, &ft2);
31884 	if (!ret) {
31885 		DUK_D(DUK_DPRINT("FileTimeToLocalFileTime() failed, return tzoffset 0"));
31886 		return 0;
31887 	}
31888 
31889 	ret = FileTimeToSystemTime((const FILETIME *) &ft2, &st2);
31890 	if (!ret) {
31891 		DUK_D(DUK_DPRINT("FileTimeToSystemTime() failed, return tzoffset 0"));
31892 		return 0;
31893 	}
31894 	duk__convert_systime_to_ularge((const SYSTEMTIME *) &st2, &tmp2);
31895 
31896 	return (duk_int_t) (((LONGLONG) tmp2.QuadPart - (LONGLONG) tmp1.QuadPart) / DUK_I64_CONSTANT(10000000));  /* seconds */
31897 }
31898 #endif  /* DUK_USE_DATE_TZO_WINDOWS_NO_DST */
31899 
31900 #if defined(DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC)
duk_bi_date_get_monotonic_time_windows_qpc(void)31901 DUK_INTERNAL duk_double_t duk_bi_date_get_monotonic_time_windows_qpc(void) {
31902 	LARGE_INTEGER count, freq;
31903 
31904 	/* There are legacy issues with QueryPerformanceCounter():
31905 	 * - Potential jumps: https://support.microsoft.com/en-us/help/274323/performance-counter-value-may-unexpectedly-leap-forward
31906 	 * - Differences between cores (XP): https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx#qpc_support_in_windows_versions
31907 	 *
31908 	 * We avoid these by enabling QPC by default only for Vista or later.
31909 	 */
31910 
31911 	if (QueryPerformanceCounter(&count) && QueryPerformanceFrequency(&freq)) {
31912 		/* XXX: QueryPerformanceFrequency() can be cached */
31913 		return (duk_double_t) count.QuadPart / (duk_double_t) freq.QuadPart * 1000.0;
31914 	} else {
31915 		/* MSDN: "On systems that run Windows XP or later, the function
31916 		 * will always succeed and will thus never return zero."
31917 		 * Provide minimal error path just in case user enables this
31918 		 * feature in pre-XP Windows.
31919 		 */
31920 		return 0.0;
31921 	}
31922 }
31923 #endif  /* DUK_USE_GET_MONOTONIC_TIME_WINDOWS_QPC */
31924 #line 1 "duk_bi_duktape.c"
31925 /*
31926  *  Duktape built-ins
31927  *
31928  *  Size optimization note: it might seem that vararg multipurpose functions
31929  *  like fin(), enc(), and dec() are not very size optimal, but using a single
31930  *  user-visible ECMAScript function saves a lot of run-time footprint; each
31931  *  Function instance takes >100 bytes.  Using a shared native helper and a
31932  *  'magic' value won't save much if there are multiple Function instances
31933  *  anyway.
31934  */
31935 
31936 /* #include duk_internal.h -> already included */
31937 
31938 #if defined(DUK_USE_DUKTAPE_BUILTIN)
31939 
duk_bi_duktape_object_info(duk_hthread * thr)31940 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_info(duk_hthread *thr) {
31941 	duk_inspect_value(thr, -1);
31942 	return 1;
31943 }
31944 
duk_bi_duktape_object_act(duk_hthread * thr)31945 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_act(duk_hthread *thr) {
31946 	duk_int_t level;
31947 
31948 	level = duk_to_int(thr, 0);
31949 	duk_inspect_callstack_entry(thr, level);
31950 	return 1;
31951 }
31952 
duk_bi_duktape_object_gc(duk_hthread * thr)31953 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_gc(duk_hthread *thr) {
31954 	duk_small_uint_t flags;
31955 
31956 	flags = (duk_small_uint_t) duk_get_uint(thr, 0);
31957 	duk_heap_mark_and_sweep(thr->heap, flags);
31958 
31959 	/* XXX: Not sure what the best return value would be in the API.
31960 	 * Return true for now.
31961 	 */
31962 	duk_push_true(thr);
31963 	return 1;
31964 }
31965 
31966 #if defined(DUK_USE_FINALIZER_SUPPORT)
duk_bi_duktape_object_fin(duk_hthread * thr)31967 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_fin(duk_hthread *thr) {
31968 	(void) duk_require_hobject(thr, 0);
31969 	if (duk_get_top(thr) >= 2) {
31970 		/* Set: currently a finalizer is disabled by setting it to
31971 		 * undefined; this does not remove the property at the moment.
31972 		 * The value could be type checked to be either a function
31973 		 * or something else; if something else, the property could
31974 		 * be deleted.  Must use duk_set_finalizer() to keep
31975 		 * DUK_HOBJECT_FLAG_HAVE_FINALIZER in sync.
31976 		 */
31977 		duk_set_top(thr, 2);
31978 		duk_set_finalizer(thr, 0);
31979 		return 0;
31980 	} else {
31981 		/* Get. */
31982 		DUK_ASSERT(duk_get_top(thr) == 1);
31983 		duk_get_finalizer(thr, 0);
31984 		return 1;
31985 	}
31986 }
31987 #endif  /* DUK_USE_FINALIZER_SUPPORT */
31988 
duk_bi_duktape_object_enc(duk_hthread * thr)31989 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_enc(duk_hthread *thr) {
31990 	duk_hstring *h_str;
31991 
31992 	/* Vararg function: must be careful to check/require arguments.
31993 	 * The JSON helpers accept invalid indices and treat them like
31994 	 * non-existent optional parameters.
31995 	 */
31996 
31997 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons. */
31998 	duk_require_valid_index(thr, 1);
31999 
32000 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32001 		duk_set_top(thr, 2);
32002 		duk_hex_encode(thr, 1);
32003 		DUK_ASSERT_TOP(thr, 2);
32004 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32005 		duk_set_top(thr, 2);
32006 		duk_base64_encode(thr, 1);
32007 		DUK_ASSERT_TOP(thr, 2);
32008 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32009 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32010 		duk_bi_json_stringify_helper(thr,
32011 		                             1 /*idx_value*/,
32012 		                             2 /*idx_replacer*/,
32013 		                             3 /*idx_space*/,
32014 		                             DUK_JSON_FLAG_EXT_CUSTOM |
32015 		                             DUK_JSON_FLAG_ASCII_ONLY |
32016 		                             DUK_JSON_FLAG_AVOID_KEY_QUOTES /*flags*/);
32017 #endif
32018 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32019 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32020 		duk_bi_json_stringify_helper(thr,
32021 		                             1 /*idx_value*/,
32022 		                             2 /*idx_replacer*/,
32023 		                             3 /*idx_space*/,
32024 		                             DUK_JSON_FLAG_EXT_COMPATIBLE |
32025 		                             DUK_JSON_FLAG_ASCII_ONLY /*flags*/);
32026 #endif
32027 	} else {
32028 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32029 	}
32030 	return 1;
32031 }
32032 
duk_bi_duktape_object_dec(duk_hthread * thr)32033 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_dec(duk_hthread *thr) {
32034 	duk_hstring *h_str;
32035 
32036 	/* Vararg function: must be careful to check/require arguments.
32037 	 * The JSON helpers accept invalid indices and treat them like
32038 	 * non-existent optional parameters.
32039 	 */
32040 
32041 	h_str = duk_require_hstring(thr, 0);  /* Could reject symbols, but no point: won't match comparisons */
32042 	duk_require_valid_index(thr, 1);
32043 
32044 	if (h_str == DUK_HTHREAD_STRING_HEX(thr)) {
32045 		duk_set_top(thr, 2);
32046 		duk_hex_decode(thr, 1);
32047 		DUK_ASSERT_TOP(thr, 2);
32048 	} else if (h_str == DUK_HTHREAD_STRING_BASE64(thr)) {
32049 		duk_set_top(thr, 2);
32050 		duk_base64_decode(thr, 1);
32051 		DUK_ASSERT_TOP(thr, 2);
32052 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JX)
32053 	} else if (h_str == DUK_HTHREAD_STRING_JX(thr)) {
32054 		duk_bi_json_parse_helper(thr,
32055 		                         1 /*idx_value*/,
32056 		                         2 /*idx_replacer*/,
32057 		                         DUK_JSON_FLAG_EXT_CUSTOM /*flags*/);
32058 #endif
32059 #if defined(DUK_USE_JSON_SUPPORT) && defined(DUK_USE_JC)
32060 	} else if (h_str == DUK_HTHREAD_STRING_JC(thr)) {
32061 		duk_bi_json_parse_helper(thr,
32062 		                         1 /*idx_value*/,
32063 		                         2 /*idx_replacer*/,
32064 		                         DUK_JSON_FLAG_EXT_COMPATIBLE /*flags*/);
32065 #endif
32066 	} else {
32067 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
32068 	}
32069 	return 1;
32070 }
32071 
32072 /*
32073  *  Compact an object
32074  */
32075 
duk_bi_duktape_object_compact(duk_hthread * thr)32076 DUK_INTERNAL duk_ret_t duk_bi_duktape_object_compact(duk_hthread *thr) {
32077 	DUK_ASSERT_TOP(thr, 1);
32078 	duk_compact(thr, 0);
32079 	return 1;  /* return the argument object */
32080 }
32081 
32082 #endif  /* DUK_USE_DUKTAPE_BUILTIN */
32083 #line 1 "duk_bi_encoding.c"
32084 /*
32085  *  WHATWG Encoding API built-ins
32086  *
32087  *  API specification: https://encoding.spec.whatwg.org/#api
32088  *  Web IDL: https://www.w3.org/TR/WebIDL/
32089  */
32090 
32091 /* #include duk_internal.h -> already included */
32092 
32093 /*
32094  *  Data structures for encoding/decoding
32095  */
32096 
32097 typedef struct {
32098 	duk_uint8_t *out;      /* where to write next byte(s) */
32099 	duk_codepoint_t lead;  /* lead surrogate */
32100 } duk__encode_context;
32101 
32102 typedef struct {
32103 	/* UTF-8 decoding state */
32104 	duk_codepoint_t codepoint;  /* built up incrementally */
32105 	duk_uint8_t upper;          /* max value of next byte (decode error otherwise) */
32106 	duk_uint8_t lower;          /* min value of next byte (ditto) */
32107 	duk_uint8_t needed;         /* how many more bytes we need */
32108 	duk_uint8_t bom_handled;    /* BOM seen or no longer expected */
32109 
32110 	/* Decoder configuration */
32111 	duk_uint8_t fatal;
32112 	duk_uint8_t ignore_bom;
32113 } duk__decode_context;
32114 
32115 /* The signed duk_codepoint_t type is used to signal a decoded codepoint
32116  * (>= 0) or various other states using negative values.
32117  */
32118 #define DUK__CP_CONTINUE   (-1)  /* continue to next byte, no completed codepoint */
32119 #define DUK__CP_ERROR      (-2)  /* decoding error */
32120 #define DUK__CP_RETRY      (-3)  /* decoding error; retry last byte */
32121 
32122 /*
32123  *  Raw helpers for encoding/decoding
32124  */
32125 
32126 /* Emit UTF-8 (= CESU-8) encoded U+FFFD (replacement char), i.e. ef bf bd. */
duk__utf8_emit_repl(duk_uint8_t * ptr)32127 DUK_LOCAL duk_uint8_t *duk__utf8_emit_repl(duk_uint8_t *ptr) {
32128 	*ptr++ = 0xef;
32129 	*ptr++ = 0xbf;
32130 	*ptr++ = 0xbd;
32131 	return ptr;
32132 }
32133 
duk__utf8_decode_init(duk__decode_context * dec_ctx)32134 DUK_LOCAL void duk__utf8_decode_init(duk__decode_context *dec_ctx) {
32135 	/* (Re)init the decoding state of 'dec_ctx' but leave decoder
32136 	 * configuration fields untouched.
32137 	 */
32138 	dec_ctx->codepoint = 0x0000L;
32139 	dec_ctx->upper = 0xbf;
32140 	dec_ctx->lower = 0x80;
32141 	dec_ctx->needed = 0;
32142 	dec_ctx->bom_handled = 0;
32143 }
32144 
duk__utf8_decode_next(duk__decode_context * dec_ctx,duk_uint8_t x)32145 DUK_LOCAL duk_codepoint_t duk__utf8_decode_next(duk__decode_context *dec_ctx, duk_uint8_t x) {
32146 	/*
32147 	 *  UTF-8 algorithm based on the Encoding specification:
32148 	 *  https://encoding.spec.whatwg.org/#utf-8-decoder
32149 	 *
32150 	 *  Two main states: decoding initial byte vs. decoding continuation
32151 	 *  bytes.  Shortest length encoding is validated by restricting the
32152 	 *  allowed range of first continuation byte using 'lower' and 'upper'.
32153 	 */
32154 
32155 	if (dec_ctx->needed == 0) {
32156 		/* process initial byte */
32157 		if (x <= 0x7f) {
32158 			/* U+0000-U+007F, 1 byte (ASCII) */
32159 			return (duk_codepoint_t) x;
32160 		} else if (x >= 0xc2 && x <= 0xdf) {
32161 			/* U+0080-U+07FF, 2 bytes */
32162 			dec_ctx->needed = 1;
32163 			dec_ctx->codepoint = x & 0x1f;
32164 			DUK_ASSERT(dec_ctx->lower == 0x80);
32165 			DUK_ASSERT(dec_ctx->upper == 0xbf);
32166 			return DUK__CP_CONTINUE;
32167 		} else if (x >= 0xe0 && x <= 0xef) {
32168 			/* U+0800-U+FFFF, 3 bytes */
32169 			if (x == 0xe0) {
32170 				dec_ctx->lower = 0xa0;
32171 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32172 			} else if (x == 0xed) {
32173 				DUK_ASSERT(dec_ctx->lower == 0x80);
32174 				dec_ctx->upper = 0x9f;
32175 			}
32176 			dec_ctx->needed = 2;
32177 			dec_ctx->codepoint = x & 0x0f;
32178 			return DUK__CP_CONTINUE;
32179 		} else if (x >= 0xf0 && x <= 0xf4) {
32180 			/* U+010000-U+10FFFF, 4 bytes */
32181 			if (x == 0xf0) {
32182 				dec_ctx->lower = 0x90;
32183 				DUK_ASSERT(dec_ctx->upper == 0xbf);
32184 			} else if (x == 0xf4) {
32185 				DUK_ASSERT(dec_ctx->lower == 0x80);
32186 				dec_ctx->upper = 0x8f;
32187 			}
32188 			dec_ctx->needed = 3;
32189 			dec_ctx->codepoint = x & 0x07;
32190 			return DUK__CP_CONTINUE;
32191 		} else {
32192 			/* not a legal initial byte */
32193 			return DUK__CP_ERROR;
32194 		}
32195 	} else {
32196 		/* process continuation byte */
32197 		if (x >= dec_ctx->lower && x <= dec_ctx->upper) {
32198 			dec_ctx->lower = 0x80;
32199 			dec_ctx->upper = 0xbf;
32200 			dec_ctx->codepoint = (dec_ctx->codepoint << 6) | (x & 0x3f);
32201 			if (--dec_ctx->needed > 0) {
32202 				/* need more bytes */
32203 				return DUK__CP_CONTINUE;
32204 			} else {
32205 				/* got a codepoint */
32206 				duk_codepoint_t ret;
32207 				DUK_ASSERT(dec_ctx->codepoint <= 0x10ffffL);  /* Decoding rules guarantee. */
32208 				ret = dec_ctx->codepoint;
32209 				dec_ctx->codepoint = 0x0000L;
32210 				dec_ctx->needed = 0;
32211 				return ret;
32212 			}
32213 		} else {
32214 			/* We just encountered an illegal UTF-8 continuation byte.  This might
32215 			 * be the initial byte of the next character; if we return a plain
32216 			 * error status and the decoder is in replacement mode, the character
32217 			 * will be masked.  We still need to alert the caller to the error
32218 			 * though.
32219 			 */
32220 			dec_ctx->codepoint = 0x0000L;
32221 			dec_ctx->needed = 0;
32222 			dec_ctx->lower = 0x80;
32223 			dec_ctx->upper = 0xbf;
32224 			return DUK__CP_RETRY;
32225 		}
32226 	}
32227 }
32228 
32229 #if defined(DUK_USE_ENCODING_BUILTINS)
duk__utf8_encode_char(void * udata,duk_codepoint_t codepoint)32230 DUK_LOCAL void duk__utf8_encode_char(void *udata, duk_codepoint_t codepoint) {
32231 	duk__encode_context *enc_ctx;
32232 
32233 	DUK_ASSERT(codepoint >= 0);
32234 	enc_ctx = (duk__encode_context *) udata;
32235 	DUK_ASSERT(enc_ctx != NULL);
32236 
32237 #if !defined(DUK_USE_PREFER_SIZE)
32238 	if (codepoint <= 0x7f && enc_ctx->lead == 0x0000L) {
32239 		/* Fast path for ASCII. */
32240 		*enc_ctx->out++ = (duk_uint8_t) codepoint;
32241 		return;
32242 	}
32243 #endif
32244 
32245 	if (DUK_UNLIKELY(codepoint > 0x10ffffL)) {
32246 		/* cannot legally encode in UTF-8 */
32247 		codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32248 	} else if (codepoint >= 0xd800L && codepoint <= 0xdfffL) {
32249 		if (codepoint <= 0xdbffL) {
32250 			/* high surrogate */
32251 			duk_codepoint_t prev_lead = enc_ctx->lead;
32252 			enc_ctx->lead = codepoint;
32253 			if (prev_lead == 0x0000L) {
32254 				/* high surrogate, no output */
32255 				return;
32256 			} else {
32257 				/* consecutive high surrogates, consider first one unpaired */
32258 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32259 			}
32260 		} else {
32261 			/* low surrogate */
32262 			if (enc_ctx->lead != 0x0000L) {
32263 				codepoint = (duk_codepoint_t) (0x010000L + ((enc_ctx->lead - 0xd800L) << 10) + (codepoint - 0xdc00L));
32264 				enc_ctx->lead = 0x0000L;
32265 			} else {
32266 				/* unpaired low surrogate */
32267 				DUK_ASSERT(enc_ctx->lead == 0x0000L);
32268 				codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32269 			}
32270 		}
32271 	} else {
32272 		if (enc_ctx->lead != 0x0000L) {
32273 			/* unpaired high surrogate: emit replacement character and the input codepoint */
32274 			enc_ctx->lead = 0x0000L;
32275 			enc_ctx->out = duk__utf8_emit_repl(enc_ctx->out);
32276 		}
32277 	}
32278 
32279 	/* Codepoint may be original input, a decoded surrogate pair, or may
32280 	 * have been replaced with U+FFFD.
32281 	 */
32282 	enc_ctx->out += duk_unicode_encode_xutf8((duk_ucodepoint_t) codepoint, enc_ctx->out);
32283 }
32284 #endif  /* DUK_USE_ENCODING_BUILTINS */
32285 
32286 /* Shared helper for buffer-to-string using a TextDecoder() compatible UTF-8
32287  * decoder.
32288  */
duk__decode_helper(duk_hthread * thr,duk__decode_context * dec_ctx)32289 DUK_LOCAL duk_ret_t duk__decode_helper(duk_hthread *thr, duk__decode_context *dec_ctx) {
32290 	const duk_uint8_t *input;
32291 	duk_size_t len = 0;
32292 	duk_size_t len_tmp;
32293 	duk_bool_t stream = 0;
32294 	duk_codepoint_t codepoint;
32295 	duk_uint8_t *output;
32296 	const duk_uint8_t *in;
32297 	duk_uint8_t *out;
32298 
32299 	DUK_ASSERT(dec_ctx != NULL);
32300 
32301 	/* Careful with input buffer pointer: any side effects involving
32302 	 * code execution (e.g. getters, coercion calls, and finalizers)
32303 	 * may cause a resize and invalidate a pointer we've read.  This
32304 	 * is why the pointer is actually looked up at the last minute.
32305 	 * Argument validation must still happen first to match WHATWG
32306 	 * required side effect order.
32307 	 */
32308 
32309 	if (duk_is_undefined(thr, 0)) {
32310 		duk_push_fixed_buffer_nozero(thr, 0);
32311 		duk_replace(thr, 0);
32312 	}
32313 	(void) duk_require_buffer_data(thr, 0, &len);  /* Need 'len', avoid pointer. */
32314 
32315 	if (duk_check_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32316 	                                DUK_TYPE_MASK_NULL |
32317 	                                DUK_TYPE_MASK_NONE)) {
32318 		/* Use defaults, treat missing value like undefined. */
32319 	} else {
32320 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_UNDEFINED |
32321 	                                      DUK_TYPE_MASK_NULL |
32322 	                                      DUK_TYPE_MASK_LIGHTFUNC |
32323 	                                      DUK_TYPE_MASK_BUFFER |
32324 		                              DUK_TYPE_MASK_OBJECT);
32325 		if (duk_get_prop_literal(thr, 1, "stream")) {
32326 			stream = duk_to_boolean(thr, -1);
32327 		}
32328 	}
32329 
32330 	/* Allowance is 3*len in the general case because all bytes may potentially
32331 	 * become U+FFFD.  If the first byte completes a non-BMP codepoint it will
32332 	 * decode to a CESU-8 surrogate pair (6 bytes) so we allow 3 extra bytes to
32333 	 * compensate: (1*3)+3 = 6.  Non-BMP codepoints are safe otherwise because
32334 	 * the 4->6 expansion is well under the 3x allowance.
32335 	 *
32336 	 * XXX: As with TextEncoder, need a better buffer allocation strategy here.
32337 	 */
32338 	if (len >= (DUK_HBUFFER_MAX_BYTELEN / 3) - 3) {
32339 		DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32340 		DUK_WO_NORETURN(return 0;);
32341 	}
32342 	output = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, 3 + (3 * len));  /* used parts will be always manually written over */
32343 
32344 	input = (const duk_uint8_t *) duk_get_buffer_data(thr, 0, &len_tmp);
32345 	DUK_ASSERT(input != NULL || len == 0);
32346 	if (DUK_UNLIKELY(len != len_tmp)) {
32347 		/* Very unlikely but possible: source buffer was resized by
32348 		 * a side effect when fixed buffer was pushed.  Output buffer
32349 		 * may not be large enough to hold output, so just fail if
32350 		 * length has changed.
32351 		 */
32352 		DUK_D(DUK_DPRINT("input buffer resized by side effect, fail"));
32353 		goto fail_type;
32354 	}
32355 
32356 	/* From this point onwards it's critical that no side effect occur
32357 	 * which may disturb 'input': finalizer execution, property accesses,
32358 	 * active coercions, etc.  Even an allocation related mark-and-sweep
32359 	 * may affect the pointer because it may trigger a pending finalizer.
32360 	 */
32361 
32362 	in = input;
32363 	out = output;
32364 	while (in < input + len) {
32365 		codepoint = duk__utf8_decode_next(dec_ctx, *in++);
32366 		if (codepoint < 0) {
32367 			if (codepoint == DUK__CP_CONTINUE) {
32368 				continue;
32369 			}
32370 
32371 			/* Decoding error with or without retry. */
32372 			DUK_ASSERT(codepoint == DUK__CP_ERROR || codepoint == DUK__CP_RETRY);
32373 			if (codepoint == DUK__CP_RETRY) {
32374 				--in;  /* retry last byte */
32375 			}
32376 			/* replacement mode: replace with U+FFFD */
32377 			codepoint = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
32378 			if (dec_ctx->fatal) {
32379 				/* fatal mode: throw a TypeError */
32380 				goto fail_type;
32381 			}
32382 			/* Continue with 'codepoint', Unicode replacement. */
32383 		}
32384 		DUK_ASSERT(codepoint >= 0x0000L && codepoint <= 0x10ffffL);
32385 
32386 		if (!dec_ctx->bom_handled) {
32387 			dec_ctx->bom_handled = 1;
32388 			if (codepoint == 0xfeffL && !dec_ctx->ignore_bom) {
32389 				continue;
32390 			}
32391 		}
32392 
32393 		out += duk_unicode_encode_cesu8((duk_ucodepoint_t) codepoint, out);
32394 		DUK_ASSERT(out <= output + (3 + (3 * len)));
32395 	}
32396 
32397 	if (!stream) {
32398 		if (dec_ctx->needed != 0) {
32399 			/* truncated sequence at end of buffer */
32400 			if (dec_ctx->fatal) {
32401 				goto fail_type;
32402 			} else {
32403 				out += duk_unicode_encode_cesu8(DUK_UNICODE_CP_REPLACEMENT_CHARACTER, out);
32404 				DUK_ASSERT(out <= output + (3 + (3 * len)));
32405 			}
32406 		}
32407 		duk__utf8_decode_init(dec_ctx);  /* Initialize decoding state for potential reuse. */
32408 	}
32409 
32410 	/* Output buffer is fixed and thus stable even if there had been
32411 	 * side effects (which there shouldn't be).
32412 	 */
32413 	duk_push_lstring(thr, (const char *) output, (duk_size_t) (out - output));
32414 	return 1;
32415 
32416  fail_type:
32417 	DUK_ERROR_TYPE(thr, DUK_STR_UTF8_DECODE_FAILED);
32418 	DUK_WO_NORETURN(return 0;);
32419 }
32420 
32421 /*
32422  *  Built-in bindings
32423  */
32424 
32425 #if defined(DUK_USE_ENCODING_BUILTINS)
duk_bi_textencoder_constructor(duk_hthread * thr)32426 DUK_INTERNAL duk_ret_t duk_bi_textencoder_constructor(duk_hthread *thr) {
32427 	/* TextEncoder currently requires no persistent state, so the constructor
32428 	 * does nothing on purpose.
32429 	 */
32430 
32431 	duk_require_constructor_call(thr);
32432 	return 0;
32433 }
32434 
duk_bi_textencoder_prototype_encoding_getter(duk_hthread * thr)32435 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encoding_getter(duk_hthread *thr) {
32436 	duk_push_literal(thr, "utf-8");
32437 	return 1;
32438 }
32439 
duk_bi_textencoder_prototype_encode(duk_hthread * thr)32440 DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_hthread *thr) {
32441 	duk__encode_context enc_ctx;
32442 	duk_size_t len;
32443 	duk_size_t final_len;
32444 	duk_uint8_t *output;
32445 
32446 	DUK_ASSERT_TOP(thr, 1);
32447 	if (duk_is_undefined(thr, 0)) {
32448 		len = 0;
32449 	} else {
32450 		duk_hstring *h_input;
32451 
32452 		h_input = duk_to_hstring(thr, 0);
32453 		DUK_ASSERT(h_input != NULL);
32454 
32455 		len = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_input);
32456 		if (len >= DUK_HBUFFER_MAX_BYTELEN / 3) {
32457 			DUK_ERROR_TYPE(thr, DUK_STR_RESULT_TOO_LONG);
32458 			DUK_WO_NORETURN(return 0;);
32459 		}
32460 	}
32461 
32462 	/* Allowance is 3*len because all bytes can potentially be replaced with
32463 	 * U+FFFD -- which rather inconveniently encodes to 3 bytes in UTF-8.
32464 	 * Rely on dynamic buffer data pointer stability: no other code has
32465 	 * access to the data pointer.
32466 	 *
32467 	 * XXX: The buffer allocation strategy used here is rather inefficient.
32468 	 * Maybe switch to a chunk-based strategy, or preprocess the string to
32469 	 * figure out the space needed ahead of time?
32470 	 */
32471 	DUK_ASSERT(3 * len >= len);
32472 	output = (duk_uint8_t *) duk_push_dynamic_buffer(thr, 3 * len);
32473 
32474 	if (len > 0) {
32475 		DUK_ASSERT(duk_is_string(thr, 0));  /* True if len > 0. */
32476 
32477 		/* XXX: duk_decode_string() is used to process the input
32478 		 * string.  For standard ECMAScript strings, represented
32479 		 * internally as CESU-8, this is fine.  However, behavior
32480 		 * beyond CESU-8 is not very strict: codepoints using an
32481 		 * extended form of UTF-8 are also accepted, and invalid
32482 		 * codepoint sequences (which are allowed in Duktape strings)
32483 		 * are not handled as well as they could (e.g. invalid
32484 		 * continuation bytes may mask following codepoints).
32485 		 * This is how ECMAScript code would also see such strings.
32486 		 * Maybe replace duk_decode_string() with an explicit strict
32487 		 * CESU-8 decoder here?
32488 		 */
32489 		enc_ctx.lead = 0x0000L;
32490 		enc_ctx.out = output;
32491 		duk_decode_string(thr, 0, duk__utf8_encode_char, (void *) &enc_ctx);
32492 		if (enc_ctx.lead != 0x0000L) {
32493 			/* unpaired high surrogate at end of string */
32494 			enc_ctx.out = duk__utf8_emit_repl(enc_ctx.out);
32495 			DUK_ASSERT(enc_ctx.out <= output + (3 * len));
32496 		}
32497 
32498 		/* The output buffer is usually very much oversized, so shrink it to
32499 		 * actually needed size.  Pointer stability assumed up to this point.
32500 		 */
32501 		DUK_ASSERT_TOP(thr, 2);
32502 		DUK_ASSERT(output == (duk_uint8_t *) duk_get_buffer_data(thr, -1, NULL));
32503 
32504 		final_len = (duk_size_t) (enc_ctx.out - output);
32505 		duk_resize_buffer(thr, -1, final_len);
32506 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
32507 	} else {
32508 		final_len = 0;
32509 	}
32510 
32511 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
32512 	 * be backed by a dynamic buffer which differs from e.g. Uint8Arrays
32513 	 * created as 'new Uint8Array(N)'.  ECMAScript code won't see the
32514 	 * difference but C code will.  When bufferobjects are not supported,
32515 	 * returns a plain dynamic buffer.
32516 	 */
32517 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
32518 	duk_push_buffer_object(thr, -1, 0, final_len, DUK_BUFOBJ_UINT8ARRAY);
32519 #endif
32520 	return 1;
32521 }
32522 
duk_bi_textdecoder_constructor(duk_hthread * thr)32523 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_constructor(duk_hthread *thr) {
32524 	duk__decode_context *dec_ctx;
32525 	duk_bool_t fatal = 0;
32526 	duk_bool_t ignore_bom = 0;
32527 
32528 	DUK_ASSERT_TOP(thr, 2);
32529 	duk_require_constructor_call(thr);
32530 	if (!duk_is_undefined(thr, 0)) {
32531 		/* XXX: For now ignore 'label' (encoding identifier). */
32532 		duk_to_string(thr, 0);
32533 	}
32534 	if (!duk_is_null_or_undefined(thr, 1)) {
32535 		if (duk_get_prop_literal(thr, 1, "fatal")) {
32536 			fatal = duk_to_boolean(thr, -1);
32537 		}
32538 		if (duk_get_prop_literal(thr, 1, "ignoreBOM")) {
32539 			ignore_bom = duk_to_boolean(thr, -1);
32540 		}
32541 	}
32542 
32543 	duk_push_this(thr);
32544 
32545 	/* The decode context is not assumed to be zeroed; all fields are
32546 	 * initialized explicitly.
32547 	 */
32548 	dec_ctx = (duk__decode_context *) duk_push_fixed_buffer(thr, sizeof(duk__decode_context));
32549 	dec_ctx->fatal = (duk_uint8_t) fatal;
32550 	dec_ctx->ignore_bom = (duk_uint8_t) ignore_bom;
32551 	duk__utf8_decode_init(dec_ctx);  /* Initializes remaining fields. */
32552 
32553 	duk_put_prop_literal(thr, -2, DUK_INTERNAL_SYMBOL("Context"));
32554 	return 0;
32555 }
32556 
32557 /* Get TextDecoder context from 'this'; leaves garbage on stack. */
duk__get_textdecoder_context(duk_hthread * thr)32558 DUK_LOCAL duk__decode_context *duk__get_textdecoder_context(duk_hthread *thr) {
32559 	duk__decode_context *dec_ctx;
32560 	duk_push_this(thr);
32561 	duk_get_prop_literal(thr, -1, DUK_INTERNAL_SYMBOL("Context"));
32562 	dec_ctx = (duk__decode_context *) duk_require_buffer(thr, -1, NULL);
32563 	DUK_ASSERT(dec_ctx != NULL);
32564 	return dec_ctx;
32565 }
32566 
duk_bi_textdecoder_prototype_shared_getter(duk_hthread * thr)32567 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_shared_getter(duk_hthread *thr) {
32568 	duk__decode_context *dec_ctx;
32569 	duk_int_t magic;
32570 
32571 	dec_ctx = duk__get_textdecoder_context(thr);
32572 	magic = duk_get_current_magic(thr);
32573 	switch (magic) {
32574 	case 0:
32575 		/* Encoding is now fixed, so _Context lookup is only needed to
32576 		 * validate the 'this' binding (TypeError if not TextDecoder-like).
32577 		 */
32578 		duk_push_literal(thr, "utf-8");
32579 		break;
32580 	case 1:
32581 		duk_push_boolean(thr, dec_ctx->fatal);
32582 		break;
32583 	default:
32584 		duk_push_boolean(thr, dec_ctx->ignore_bom);
32585 		break;
32586 	}
32587 
32588 	return 1;
32589 }
32590 
duk_bi_textdecoder_prototype_decode(duk_hthread * thr)32591 DUK_INTERNAL duk_ret_t duk_bi_textdecoder_prototype_decode(duk_hthread *thr) {
32592 	duk__decode_context *dec_ctx;
32593 
32594 	dec_ctx = duk__get_textdecoder_context(thr);
32595 	return duk__decode_helper(thr, dec_ctx);
32596 }
32597 #endif  /* DUK_USE_ENCODING_BUILTINS */
32598 
32599 /*
32600  *  Internal helper for Node.js Buffer
32601  */
32602 
32603 /* Internal helper used for Node.js Buffer .toString().  Value stack convention
32604  * is currently odd: it mimics TextDecoder .decode() so that argument must be at
32605  * index 0, and decode options (not present for Buffer) at index 1.  Return value
32606  * is a Duktape/C function return value.
32607  */
duk_textdecoder_decode_utf8_nodejs(duk_hthread * thr)32608 DUK_INTERNAL duk_ret_t duk_textdecoder_decode_utf8_nodejs(duk_hthread *thr) {
32609 	duk__decode_context dec_ctx;
32610 
32611 	dec_ctx.fatal = 0;  /* use replacement chars */
32612 	dec_ctx.ignore_bom = 1;  /* ignore BOMs (matches Node.js Buffer .toString()) */
32613 	duk__utf8_decode_init(&dec_ctx);
32614 
32615 	return duk__decode_helper(thr, &dec_ctx);
32616 }
32617 
32618 /* automatic undefs */
32619 #undef DUK__CP_CONTINUE
32620 #undef DUK__CP_ERROR
32621 #undef DUK__CP_RETRY
32622 #line 1 "duk_bi_error.c"
32623 /*
32624  *  Error built-ins
32625  */
32626 
32627 /* #include duk_internal.h -> already included */
32628 
duk_bi_error_constructor_shared(duk_hthread * thr)32629 DUK_INTERNAL duk_ret_t duk_bi_error_constructor_shared(duk_hthread *thr) {
32630 	/* Behavior for constructor and non-constructor call is
32631 	 * the same except for augmenting the created error.  When
32632 	 * called as a constructor, the caller (duk_new()) will handle
32633 	 * augmentation; when called as normal function, we need to do
32634 	 * it here.
32635 	 */
32636 
32637 	duk_small_int_t bidx_prototype = duk_get_current_magic(thr);
32638 
32639 	/* same for both error and each subclass like TypeError */
32640 	duk_uint_t flags_and_class = DUK_HOBJECT_FLAG_EXTENSIBLE |
32641 	                             DUK_HOBJECT_FLAG_FASTREFS |
32642 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ERROR);
32643 
32644 	(void) duk_push_object_helper(thr, flags_and_class, bidx_prototype);
32645 
32646 	/* If message is undefined, the own property 'message' is not set at
32647 	 * all to save property space.  An empty message is inherited anyway.
32648 	 */
32649 	if (!duk_is_undefined(thr, 0)) {
32650 		duk_to_string(thr, 0);
32651 		duk_dup_0(thr);  /* [ message error message ] */
32652 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE, DUK_PROPDESC_FLAGS_WC);
32653 	}
32654 
32655 	/* Augment the error if called as a normal function.  __FILE__ and __LINE__
32656 	 * are not desirable in this case.
32657 	 */
32658 
32659 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
32660 	if (!duk_is_constructor_call(thr)) {
32661 		duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE);
32662 	}
32663 #endif
32664 
32665 	return 1;
32666 }
32667 
duk_bi_error_prototype_to_string(duk_hthread * thr)32668 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_to_string(duk_hthread *thr) {
32669 	/* XXX: optimize with more direct internal access */
32670 
32671 	duk_push_this(thr);
32672 	(void) duk_require_hobject_promote_mask(thr, -1, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
32673 
32674 	/* [ ... this ] */
32675 
32676 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
32677 	if (duk_is_undefined(thr, -1)) {
32678 		duk_pop(thr);
32679 		duk_push_literal(thr, "Error");
32680 	} else {
32681 		duk_to_string(thr, -1);
32682 	}
32683 
32684 	/* [ ... this name ] */
32685 
32686 	/* XXX: Are steps 6 and 7 in E5 Section 15.11.4.4 duplicated by
32687 	 * accident or are they actually needed?  The first ToString()
32688 	 * could conceivably return 'undefined'.
32689 	 */
32690 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
32691 	if (duk_is_undefined(thr, -1)) {
32692 		duk_pop(thr);
32693 		duk_push_hstring_empty(thr);
32694 	} else {
32695 		duk_to_string(thr, -1);
32696 	}
32697 
32698 	/* [ ... this name message ] */
32699 
32700 	if (duk_get_length(thr, -2) == 0) {
32701 		/* name is empty -> return message */
32702 		return 1;
32703 	}
32704 	if (duk_get_length(thr, -1) == 0) {
32705 		/* message is empty -> return name */
32706 		duk_pop(thr);
32707 		return 1;
32708 	}
32709 	duk_push_literal(thr, ": ");
32710 	duk_insert(thr, -2);  /* ... name ': ' message */
32711 	duk_concat(thr, 3);
32712 
32713 	return 1;
32714 }
32715 
32716 #if defined(DUK_USE_TRACEBACKS)
32717 
32718 /*
32719  *  Traceback handling
32720  *
32721  *  The unified helper decodes the traceback and produces various requested
32722  *  outputs.  It should be optimized for size, and may leave garbage on stack,
32723  *  only the topmost return value matters.  For instance, traceback separator
32724  *  and decoded strings are pushed even when looking for filename only.
32725  *
32726  *  NOTE: although _Tracedata is an internal property, user code can currently
32727  *  write to the array (or replace it with something other than an array).
32728  *  The code below must tolerate arbitrary _Tracedata.  It can throw errors
32729  *  etc, but cannot cause a segfault or memory unsafe behavior.
32730  */
32731 
32732 /* constants arbitrary, chosen for small loads */
32733 #define DUK__OUTPUT_TYPE_TRACEBACK   (-1)
32734 #define DUK__OUTPUT_TYPE_FILENAME    0
32735 #define DUK__OUTPUT_TYPE_LINENUMBER  1
32736 
duk__error_getter_helper(duk_hthread * thr,duk_small_int_t output_type)32737 DUK_LOCAL duk_ret_t duk__error_getter_helper(duk_hthread *thr, duk_small_int_t output_type) {
32738 	duk_idx_t idx_td;
32739 	duk_small_int_t i;  /* traceback depth fits into 16 bits */
32740 	duk_small_int_t t;  /* stack type fits into 16 bits */
32741 	duk_small_int_t count_func = 0;  /* traceback depth ensures fits into 16 bits */
32742 	const char *str_tailcall = " tailcall";
32743 	const char *str_strict = " strict";
32744 	const char *str_construct = " construct";
32745 	const char *str_prevyield = " preventsyield";
32746 	const char *str_directeval = " directeval";
32747 	const char *str_empty = "";
32748 
32749 	DUK_ASSERT_TOP(thr, 0);  /* fixed arg count */
32750 
32751 	duk_push_this(thr);
32752 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TRACEDATA);
32753 	idx_td = duk_get_top_index(thr);
32754 
32755 	duk_push_hstring_stridx(thr, DUK_STRIDX_NEWLINE_4SPACE);
32756 	duk_push_this(thr);
32757 
32758 	/* [ ... this tracedata sep this ] */
32759 
32760 	/* XXX: skip null filename? */
32761 
32762 	if (duk_check_type(thr, idx_td, DUK_TYPE_OBJECT)) {
32763 		/* Current tracedata contains 2 entries per callstack entry. */
32764 		for (i = 0; ; i += 2) {
32765 			duk_int_t pc;
32766 			duk_uint_t line;
32767 			duk_uint_t flags;
32768 			duk_double_t d;
32769 			const char *funcname;
32770 			const char *filename;
32771 			duk_hobject *h_func;
32772 			duk_hstring *h_name;
32773 
32774 			duk_require_stack(thr, 5);
32775 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) i);
32776 			duk_get_prop_index(thr, idx_td, (duk_uarridx_t) (i + 1));
32777 			d = duk_to_number_m1(thr);
32778 			pc = duk_double_to_int_t(DUK_FMOD(d, DUK_DOUBLE_2TO32));
32779 			flags = duk_double_to_uint_t(DUK_FLOOR(d / DUK_DOUBLE_2TO32));
32780 			t = (duk_small_int_t) duk_get_type(thr, -2);
32781 
32782 			if (t == DUK_TYPE_OBJECT || t == DUK_TYPE_LIGHTFUNC) {
32783 				/*
32784 				 *  ECMAScript/native function call or lightfunc call
32785 				 */
32786 
32787 				count_func++;
32788 
32789 				/* [ ... v1(func) v2(pc+flags) ] */
32790 
32791 				/* These may be systematically omitted by Duktape
32792 				 * with certain config options, but allow user to
32793 				 * set them on a case-by-case basis.
32794 				 */
32795 				duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
32796 				duk_get_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME);
32797 
32798 #if defined(DUK_USE_PC2LINE)
32799 				line = (duk_uint_t) duk_hobject_pc2line_query(thr, -4, (duk_uint_fast32_t) pc);
32800 #else
32801 				line = 0;
32802 #endif
32803 
32804 				/* [ ... v1 v2 name filename ] */
32805 
32806 				/* When looking for .fileName/.lineNumber, blame first
32807 				 * function which has a .fileName.
32808 				 */
32809 				if (duk_is_string_notsymbol(thr, -1)) {
32810 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
32811 						return 1;
32812 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
32813 						duk_push_uint(thr, line);
32814 						return 1;
32815 					}
32816 				}
32817 
32818 				/* XXX: Change 'anon' handling here too, to use empty string for anonymous functions? */
32819 				/* XXX: Could be improved by coercing to a readable duk_tval (especially string escaping) */
32820 				h_name = duk_get_hstring_notsymbol(thr, -2);  /* may be NULL */
32821 				funcname = (h_name == NULL || h_name == DUK_HTHREAD_STRING_EMPTY_STRING(thr)) ?
32822 				           "[anon]" : (const char *) DUK_HSTRING_GET_DATA(h_name);
32823 				filename = duk_get_string_notsymbol(thr, -1);
32824 				filename = filename ? filename : "";
32825 				DUK_ASSERT(funcname != NULL);
32826 				DUK_ASSERT(filename != NULL);
32827 
32828 				h_func = duk_get_hobject(thr, -4);  /* NULL for lightfunc */
32829 
32830 				if (h_func == NULL) {
32831 					duk_push_sprintf(thr, "at %s light%s%s%s%s%s",
32832 					                 (const char *) funcname,
32833 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32834 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32835 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32836 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32837 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32838 				} else if (DUK_HOBJECT_HAS_NATFUNC(h_func)) {
32839 					duk_push_sprintf(thr, "at %s (%s) native%s%s%s%s%s",
32840 					                 (const char *) funcname,
32841 					                 (const char *) filename,
32842 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32843 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32844 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32845 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32846 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32847 				} else {
32848 					duk_push_sprintf(thr, "at %s (%s:%lu)%s%s%s%s%s",
32849 					                 (const char *) funcname,
32850 					                 (const char *) filename,
32851 					                 (unsigned long) line,
32852 					                 (const char *) ((flags & DUK_ACT_FLAG_STRICT) ? str_strict : str_empty),
32853 					                 (const char *) ((flags & DUK_ACT_FLAG_TAILCALLED) ? str_tailcall : str_empty),
32854 					                 (const char *) ((flags & DUK_ACT_FLAG_CONSTRUCT) ? str_construct : str_empty),
32855 					                 (const char *) ((flags & DUK_ACT_FLAG_DIRECT_EVAL) ? str_directeval : str_empty),
32856 					                 (const char *) ((flags & DUK_ACT_FLAG_PREVENT_YIELD) ? str_prevyield : str_empty));
32857 				}
32858 				duk_replace(thr, -5);   /* [ ... v1 v2 name filename str ] -> [ ... str v2 name filename ] */
32859 				duk_pop_3(thr);         /* -> [ ... str ] */
32860 			} else if (t == DUK_TYPE_STRING) {
32861 				const char *str_file;
32862 
32863 				/*
32864 				 *  __FILE__ / __LINE__ entry, here 'pc' is line number directly.
32865 				 *  Sometimes __FILE__ / __LINE__ is reported as the source for
32866 				 *  the error (fileName, lineNumber), sometimes not.
32867 				 */
32868 
32869 				/* [ ... v1(filename) v2(line+flags) ] */
32870 
32871 				/* When looking for .fileName/.lineNumber, blame compilation
32872 				 * or C call site unless flagged not to do so.
32873 				 */
32874 				if (!(flags & DUK_TB_FLAG_NOBLAME_FILELINE)) {
32875 					if (output_type == DUK__OUTPUT_TYPE_FILENAME) {
32876 						duk_pop(thr);
32877 						return 1;
32878 					} else if (output_type == DUK__OUTPUT_TYPE_LINENUMBER) {
32879 						duk_push_int(thr, pc);
32880 						return 1;
32881 					}
32882 				}
32883 
32884 				/* Tracedata is trusted but avoid any risk of using a NULL
32885 				 * for %s format because it has undefined behavior.  Symbols
32886 				 * don't need to be explicitly rejected as they pose no memory
32887 				 * safety issues.
32888 				 */
32889 				str_file = (const char *) duk_get_string(thr, -2);
32890 				duk_push_sprintf(thr, "at [anon] (%s:%ld) internal",
32891 				                 (const char *) (str_file ? str_file : "null"), (long) pc);
32892 				duk_replace(thr, -3);  /* [ ... v1 v2 str ] -> [ ... str v2 ] */
32893 				duk_pop(thr);          /* -> [ ... str ] */
32894 			} else {
32895 				/* unknown, ignore */
32896 				duk_pop_2(thr);
32897 				break;
32898 			}
32899 		}
32900 
32901 		if (count_func >= DUK_USE_TRACEBACK_DEPTH) {
32902 			/* Possibly truncated; there is no explicit truncation
32903 			 * marker so this is the best we can do.
32904 			 */
32905 
32906 			duk_push_hstring_stridx(thr, DUK_STRIDX_BRACKETED_ELLIPSIS);
32907 		}
32908 	}
32909 
32910 	/* [ ... this tracedata sep this str1 ... strN ] */
32911 
32912 	if (output_type != DUK__OUTPUT_TYPE_TRACEBACK) {
32913 		return 0;
32914 	} else {
32915 		/* The 'this' after 'sep' will get ToString() coerced by
32916 		 * duk_join() automatically.  We don't want to do that
32917 		 * coercion when providing .fileName or .lineNumber (GH-254).
32918 		 */
32919 		duk_join(thr, duk_get_top(thr) - (idx_td + 2) /*count, not including sep*/);
32920 		return 1;
32921 	}
32922 }
32923 
32924 /* XXX: Output type could be encoded into native function 'magic' value to
32925  * save space.  For setters the stridx could be encoded into 'magic'.
32926  */
32927 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)32928 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
32929 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_TRACEBACK);
32930 }
32931 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)32932 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
32933 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_FILENAME);
32934 }
32935 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)32936 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
32937 	return duk__error_getter_helper(thr, DUK__OUTPUT_TYPE_LINENUMBER);
32938 }
32939 
32940 #else  /* DUK_USE_TRACEBACKS */
32941 
32942 /*
32943  *  Traceback handling when tracebacks disabled.
32944  *
32945  *  The fileName / lineNumber stubs are now necessary because built-in
32946  *  data will include the accessor properties in Error.prototype.  If those
32947  *  are removed for builds without tracebacks, these can also be removed.
32948  *  'stack' should still be present and produce a ToString() equivalent:
32949  *  this is useful for user code which prints a stacktrace and expects to
32950  *  see something useful.  A normal stacktrace also begins with a ToString()
32951  *  of the error so this makes sense.
32952  */
32953 
duk_bi_error_prototype_stack_getter(duk_hthread * thr)32954 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_getter(duk_hthread *thr) {
32955 	/* XXX: remove this native function and map 'stack' accessor
32956 	 * to the toString() implementation directly.
32957 	 */
32958 	return duk_bi_error_prototype_to_string(thr);
32959 }
32960 
duk_bi_error_prototype_filename_getter(duk_hthread * thr)32961 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_getter(duk_hthread *thr) {
32962 	DUK_UNREF(thr);
32963 	return 0;
32964 }
32965 
duk_bi_error_prototype_linenumber_getter(duk_hthread * thr)32966 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_getter(duk_hthread *thr) {
32967 	DUK_UNREF(thr);
32968 	return 0;
32969 }
32970 
32971 #endif  /* DUK_USE_TRACEBACKS */
32972 
duk__error_setter_helper(duk_hthread * thr,duk_small_uint_t stridx_key)32973 DUK_LOCAL duk_ret_t duk__error_setter_helper(duk_hthread *thr, duk_small_uint_t stridx_key) {
32974 	/* Attempt to write 'stack', 'fileName', 'lineNumber' works as if
32975 	 * user code called Object.defineProperty() to create an overriding
32976 	 * own property.  This allows user code to overwrite .fileName etc
32977 	 * intuitively as e.g. "err.fileName = 'dummy'" as one might expect.
32978 	 * See https://github.com/svaarala/duktape/issues/387.
32979 	 */
32980 
32981 	DUK_ASSERT_TOP(thr, 1);  /* fixed arg count: value */
32982 
32983 	duk_push_this(thr);
32984 	duk_push_hstring_stridx(thr, stridx_key);
32985 	duk_dup_0(thr);
32986 
32987 	/* [ ... obj key value ] */
32988 
32989 	DUK_DD(DUK_DDPRINT("error setter: %!T %!T %!T",
32990 	                   duk_get_tval(thr, -3), duk_get_tval(thr, -2), duk_get_tval(thr, -1)));
32991 
32992 	duk_def_prop(thr, -3, DUK_DEFPROP_HAVE_VALUE |
32993 	                      DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE |
32994 	                      DUK_DEFPROP_HAVE_ENUMERABLE | /*not enumerable*/
32995 	                      DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE);
32996 	return 0;
32997 }
32998 
duk_bi_error_prototype_stack_setter(duk_hthread * thr)32999 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_stack_setter(duk_hthread *thr) {
33000 	return duk__error_setter_helper(thr, DUK_STRIDX_STACK);
33001 }
33002 
duk_bi_error_prototype_filename_setter(duk_hthread * thr)33003 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_filename_setter(duk_hthread *thr) {
33004 	return duk__error_setter_helper(thr, DUK_STRIDX_FILE_NAME);
33005 }
33006 
duk_bi_error_prototype_linenumber_setter(duk_hthread * thr)33007 DUK_INTERNAL duk_ret_t duk_bi_error_prototype_linenumber_setter(duk_hthread *thr) {
33008 	return duk__error_setter_helper(thr, DUK_STRIDX_LINE_NUMBER);
33009 }
33010 
33011 /* automatic undefs */
33012 #undef DUK__OUTPUT_TYPE_FILENAME
33013 #undef DUK__OUTPUT_TYPE_LINENUMBER
33014 #undef DUK__OUTPUT_TYPE_TRACEBACK
33015 #line 1 "duk_bi_function.c"
33016 /*
33017  *  Function built-ins
33018  */
33019 
33020 /* #include duk_internal.h -> already included */
33021 
33022 /* Needed even when Function built-in is disabled. */
duk_bi_function_prototype(duk_hthread * thr)33023 DUK_INTERNAL duk_ret_t duk_bi_function_prototype(duk_hthread *thr) {
33024 	/* ignore arguments, return undefined (E5 Section 15.3.4) */
33025 	DUK_UNREF(thr);
33026 	return 0;
33027 }
33028 
33029 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_constructor(duk_hthread * thr)33030 DUK_INTERNAL duk_ret_t duk_bi_function_constructor(duk_hthread *thr) {
33031 	duk_hstring *h_sourcecode;
33032 	duk_idx_t nargs;
33033 	duk_idx_t i;
33034 	duk_small_uint_t comp_flags;
33035 	duk_hcompfunc *func;
33036 	duk_hobject *outer_lex_env;
33037 	duk_hobject *outer_var_env;
33038 
33039 	/* normal and constructor calls have identical semantics */
33040 
33041 	nargs = duk_get_top(thr);
33042 	for (i = 0; i < nargs; i++) {
33043 		duk_to_string(thr, i);  /* Rejects Symbols during coercion. */
33044 	}
33045 
33046 	if (nargs == 0) {
33047 		duk_push_hstring_empty(thr);
33048 		duk_push_hstring_empty(thr);
33049 	} else if (nargs == 1) {
33050 		/* XXX: cover this with the generic >1 case? */
33051 		duk_push_hstring_empty(thr);
33052 	} else {
33053 		duk_insert(thr, 0);   /* [ arg1 ... argN-1 body] -> [body arg1 ... argN-1] */
33054 		duk_push_literal(thr, ",");
33055 		duk_insert(thr, 1);
33056 		duk_join(thr, nargs - 1);
33057 	}
33058 
33059 	/* [ body formals ], formals is comma separated list that needs to be parsed */
33060 
33061 	DUK_ASSERT_TOP(thr, 2);
33062 
33063 	/* XXX: this placeholder is not always correct, but use for now.
33064 	 * It will fail in corner cases; see test-dev-func-cons-args.js.
33065 	 */
33066 	duk_push_literal(thr, "function(");
33067 	duk_dup_1(thr);
33068 	duk_push_literal(thr, "){");
33069 	duk_dup_0(thr);
33070 	duk_push_literal(thr, "\n}");  /* Newline is important to handle trailing // comment. */
33071 	duk_concat(thr, 5);
33072 
33073 	/* [ body formals source ] */
33074 
33075 	DUK_ASSERT_TOP(thr, 3);
33076 
33077 	/* strictness is not inherited, intentional */
33078 	comp_flags = DUK_COMPILE_FUNCEXPR;
33079 
33080 	duk_push_hstring_stridx(thr, DUK_STRIDX_COMPILE);  /* XXX: copy from caller? */  /* XXX: ignored now */
33081 	h_sourcecode = duk_require_hstring(thr, -2);  /* no symbol check needed; -2 is concat'd code */
33082 	duk_js_compile(thr,
33083 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_sourcecode),
33084 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sourcecode),
33085 	               comp_flags);
33086 
33087 	/* Force .name to 'anonymous' (ES2015). */
33088 	duk_push_literal(thr, "anonymous");
33089 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33090 
33091 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
33092 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
33093 	DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) func));
33094 
33095 	/* [ body formals source template ] */
33096 
33097 	/* only outer_lex_env matters, as functions always get a new
33098 	 * variable declaration environment.
33099 	 */
33100 
33101 	outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33102 	outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
33103 
33104 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 1 /*add_auto_proto*/);
33105 
33106 	/* [ body formals source template closure ] */
33107 
33108 	return 1;
33109 }
33110 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33111 
33112 #if defined(DUK_USE_FUNCTION_BUILTIN)
duk_bi_function_prototype_to_string(duk_hthread * thr)33113 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_to_string(duk_hthread *thr) {
33114 	duk_tval *tv;
33115 
33116 	/*
33117 	 *  E5 Section 15.3.4.2 places few requirements on the output of
33118 	 *  this function: the result is implementation dependent, must
33119 	 *  follow FunctionDeclaration syntax (in particular, must have a
33120 	 *  name even for anonymous functions or functions with empty name).
33121 	 *  The output does NOT need to compile into anything useful.
33122 	 *
33123 	 *  E6 Section 19.2.3.5 changes the requirements completely: the
33124 	 *  result must either eval() to a functionally equivalent object
33125 	 *  OR eval() to a SyntaxError.
33126 	 *
33127 	 *  We opt for the SyntaxError approach for now, with a syntax that
33128 	 *  mimics V8's native function syntax:
33129 	 *
33130 	 *      'function cos() { [native code] }'
33131 	 *
33132 	 *  but extended with [ecmascript code], [bound code], and
33133 	 *  [lightfunc code].
33134 	 */
33135 
33136 	duk_push_this(thr);
33137 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
33138 	DUK_ASSERT(tv != NULL);
33139 
33140 	if (DUK_TVAL_IS_OBJECT(tv)) {
33141 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv);
33142 		const char *func_name;
33143 
33144 		/* Function name: missing/undefined is mapped to empty string,
33145 		 * otherwise coerce to string.  No handling for invalid identifier
33146 		 * characters or e.g. '{' in the function name.  This doesn't
33147 		 * really matter as long as a SyntaxError results.  Technically
33148 		 * if the name contained a suitable prefix followed by '//' it
33149 		 * might cause the result to parse without error.
33150 		 */
33151 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME);
33152 		if (duk_is_undefined(thr, -1)) {
33153 			func_name = "";
33154 		} else {
33155 			func_name = duk_to_string(thr, -1);
33156 			DUK_ASSERT(func_name != NULL);
33157 		}
33158 
33159 		if (DUK_HOBJECT_IS_COMPFUNC(obj)) {
33160 			duk_push_sprintf(thr, "function %s() { [ecmascript code] }", (const char *) func_name);
33161 		} else if (DUK_HOBJECT_IS_NATFUNC(obj)) {
33162 			duk_push_sprintf(thr, "function %s() { [native code] }", (const char *) func_name);
33163 		} else if (DUK_HOBJECT_IS_BOUNDFUNC(obj)) {
33164 			duk_push_sprintf(thr, "function %s() { [bound code] }", (const char *) func_name);
33165 		} else {
33166 			goto type_error;
33167 		}
33168 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33169 		duk_push_lightfunc_tostring(thr, tv);
33170 	} else {
33171 		goto type_error;
33172 	}
33173 
33174 	return 1;
33175 
33176  type_error:
33177 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33178 }
33179 #endif
33180 
33181 /* Always present because the native function pointer is needed in call
33182  * handling.
33183  */
duk_bi_function_prototype_call(duk_hthread * thr)33184 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_hthread *thr) {
33185 	/* .call() is dealt with in call handling by simulating its
33186 	 * effects so this function is actually never called.
33187 	 */
33188 	DUK_UNREF(thr);
33189 	return DUK_RET_TYPE_ERROR;
33190 }
33191 
duk_bi_function_prototype_apply(duk_hthread * thr)33192 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_apply(duk_hthread *thr) {
33193 	/* Like .call(), never actually called. */
33194 	DUK_UNREF(thr);
33195 	return DUK_RET_TYPE_ERROR;
33196 }
33197 
duk_bi_reflect_apply(duk_hthread * thr)33198 DUK_INTERNAL duk_ret_t duk_bi_reflect_apply(duk_hthread *thr) {
33199 	/* Like .call(), never actually called. */
33200 	DUK_UNREF(thr);
33201 	return DUK_RET_TYPE_ERROR;
33202 }
33203 
duk_bi_reflect_construct(duk_hthread * thr)33204 DUK_INTERNAL duk_ret_t duk_bi_reflect_construct(duk_hthread *thr) {
33205 	/* Like .call(), never actually called. */
33206 	DUK_UNREF(thr);
33207 	return DUK_RET_TYPE_ERROR;
33208 }
33209 
33210 #if defined(DUK_USE_FUNCTION_BUILTIN)
33211 /* Create a bound function which points to a target function which may
33212  * be bound or non-bound.  If the target is bound, the argument lists
33213  * and 'this' binding of the functions are merged and the resulting
33214  * function points directly to the non-bound target.
33215  */
duk_bi_function_prototype_bind(duk_hthread * thr)33216 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_hthread *thr) {
33217 	duk_hboundfunc *h_bound;
33218 	duk_idx_t nargs;  /* bound args, not counting 'this' binding */
33219 	duk_idx_t bound_nargs;
33220 	duk_int_t bound_len;
33221 	duk_tval *tv_prevbound;
33222 	duk_idx_t n_prevbound;
33223 	duk_tval *tv_res;
33224 	duk_tval *tv_tmp;
33225 
33226 	/* XXX: C API call, e.g. duk_push_bound_function(thr, target_idx, nargs); */
33227 
33228 	/* Vararg function, careful arg handling, e.g. thisArg may not
33229 	 * be present.
33230 	 */
33231 	nargs = duk_get_top(thr) - 1;  /* actual args, not counting 'this' binding */
33232 	if (nargs < 0) {
33233 		nargs++;
33234 		duk_push_undefined(thr);
33235 	}
33236 	DUK_ASSERT(nargs >= 0);
33237 
33238 	/* Limit 'nargs' for bound functions to guarantee arithmetic
33239 	 * below will never wrap.
33240 	 */
33241 	if (nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33242 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33243 	}
33244 
33245 	duk_push_this(thr);
33246 	duk_require_callable(thr, -1);
33247 
33248 	/* [ thisArg arg1 ... argN func ]  (thisArg+args == nargs+1 total) */
33249 	DUK_ASSERT_TOP(thr, nargs + 2);
33250 
33251 	/* Create bound function object. */
33252 	h_bound = duk_push_hboundfunc(thr);
33253 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->target));
33254 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&h_bound->this_binding));
33255 	DUK_ASSERT(h_bound->args == NULL);
33256 	DUK_ASSERT(h_bound->nargs == 0);
33257 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_bound) == NULL);
33258 
33259 	/* [ thisArg arg1 ... argN func boundFunc ] */
33260 
33261 	/* If the target is a bound function, argument lists must be
33262 	 * merged.  The 'this' binding closest to the target function
33263 	 * wins because in call handling the 'this' gets replaced over
33264 	 * and over again until we call the non-bound function.
33265 	 */
33266 	tv_prevbound = NULL;
33267 	n_prevbound = 0;
33268 	tv_tmp = DUK_GET_TVAL_POSIDX(thr, 0);
33269 	DUK_TVAL_SET_TVAL(&h_bound->this_binding, tv_tmp);
33270 	tv_tmp = DUK_GET_TVAL_NEGIDX(thr, -2);
33271 	DUK_TVAL_SET_TVAL(&h_bound->target, tv_tmp);
33272 
33273 	if (DUK_TVAL_IS_OBJECT(tv_tmp)) {
33274 		duk_hobject *h_target;
33275 		duk_hobject *bound_proto;
33276 
33277 		h_target = DUK_TVAL_GET_OBJECT(tv_tmp);
33278 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(h_target));
33279 
33280 		/* Internal prototype must be copied from the target.
33281 		 * For lightfuncs Function.prototype is used and is already
33282 		 * in place.
33283 		 */
33284 		bound_proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target);
33285 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33286 
33287 		/* The 'strict' flag is copied to get the special [[Get]] of E5.1
33288 		 * Section 15.3.5.4 to apply when a 'caller' value is a strict bound
33289 		 * function.  Not sure if this is correct, because the specification
33290 		 * is a bit ambiguous on this point but it would make sense.
33291 		 */
33292 		/* Strictness is inherited from target. */
33293 		if (DUK_HOBJECT_HAS_STRICT(h_target)) {
33294 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33295 		}
33296 
33297 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h_target)) {
33298 			duk_hboundfunc *h_boundtarget;
33299 
33300 			h_boundtarget = (duk_hboundfunc *) (void *) h_target;
33301 
33302 			/* The final function should always be non-bound, unless
33303 			 * there's a bug in the internals.  Assert for it.
33304 			 */
33305 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(&h_boundtarget->target) ||
33306 			           (DUK_TVAL_IS_OBJECT(&h_boundtarget->target) &&
33307 			            DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(&h_boundtarget->target)) &&
33308 			            !DUK_HOBJECT_IS_BOUNDFUNC(DUK_TVAL_GET_OBJECT(&h_boundtarget->target))));
33309 
33310 			DUK_TVAL_SET_TVAL(&h_bound->target, &h_boundtarget->target);
33311 			DUK_TVAL_SET_TVAL(&h_bound->this_binding, &h_boundtarget->this_binding);
33312 
33313 			tv_prevbound = h_boundtarget->args;
33314 			n_prevbound = h_boundtarget->nargs;
33315 		}
33316 	} else {
33317 		/* Lightfuncs are always strict. */
33318 		duk_hobject *bound_proto;
33319 
33320 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
33321 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_bound);
33322 		bound_proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
33323 		DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) h_bound, bound_proto);
33324 	}
33325 
33326 	DUK_TVAL_INCREF(thr, &h_bound->target);  /* old values undefined, no decref needed */
33327 	DUK_TVAL_INCREF(thr, &h_bound->this_binding);
33328 
33329 	bound_nargs = n_prevbound + nargs;
33330 	if (bound_nargs > (duk_idx_t) DUK_HBOUNDFUNC_MAX_ARGS) {
33331 		DUK_DCERROR_RANGE_INVALID_COUNT(thr);
33332 	}
33333 	tv_res = (duk_tval *) DUK_ALLOC_CHECKED(thr, ((duk_size_t) bound_nargs) * sizeof(duk_tval));
33334 	DUK_ASSERT(tv_res != NULL || bound_nargs == 0);
33335 	DUK_ASSERT(h_bound->args == NULL);
33336 	DUK_ASSERT(h_bound->nargs == 0);
33337 	h_bound->args = tv_res;
33338 	h_bound->nargs = bound_nargs;
33339 
33340 	DUK_ASSERT(n_prevbound >= 0);
33341 	duk_copy_tvals_incref(thr, tv_res, tv_prevbound, (duk_size_t) n_prevbound);
33342 	DUK_ASSERT(nargs >= 0);
33343 	duk_copy_tvals_incref(thr, tv_res + n_prevbound, DUK_GET_TVAL_POSIDX(thr, 1), (duk_size_t) nargs);
33344 
33345 	/* [ thisArg arg1 ... argN func boundFunc ] */
33346 
33347 	/* Bound function 'length' property is interesting.
33348 	 * For lightfuncs, simply read the virtual property.
33349 	 */
33350 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH);
33351 	bound_len = duk_get_int(thr, -1);  /* ES2015: no coercion */
33352 	if (bound_len < nargs) {
33353 		bound_len = 0;
33354 	} else {
33355 		bound_len -= nargs;
33356 	}
33357 	if (sizeof(duk_int_t) > 4 && bound_len > (duk_int_t) DUK_UINT32_MAX) {
33358 		bound_len = (duk_int_t) DUK_UINT32_MAX;
33359 	}
33360 	duk_pop(thr);
33361 	DUK_ASSERT(bound_len >= 0);
33362 	tv_tmp = thr->valstack_top++;
33363 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv_tmp));
33364 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv_tmp));
33365 	DUK_TVAL_SET_U32(tv_tmp, (duk_uint32_t) bound_len);  /* in-place update, fastint */
33366 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);  /* attrs in E6 Section 9.2.4 */
33367 
33368 	/* XXX: could these be virtual? */
33369 	/* Caller and arguments must use the same thrower, [[ThrowTypeError]]. */
33370 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_CALLER);
33371 	duk_xdef_prop_stridx_thrower(thr, -1, DUK_STRIDX_LC_ARGUMENTS);
33372 
33373 	/* Function name and fileName (non-standard). */
33374 	duk_push_literal(thr, "bound ");  /* ES2015 19.2.3.2. */
33375 	duk_get_prop_stridx(thr, -3, DUK_STRIDX_NAME);
33376 	if (!duk_is_string_notsymbol(thr, -1)) {
33377 		/* ES2015 has requirement to check that .name of target is a string
33378 		 * (also must check for Symbol); if not, targetName should be the
33379 		 * empty string.  ES2015 19.2.3.2.
33380 		 */
33381 		duk_pop(thr);
33382 		duk_push_hstring_empty(thr);
33383 	}
33384 	duk_concat(thr, 2);
33385 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
33386 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
33387 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME);
33388 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C);
33389 #endif
33390 
33391 	DUK_DDD(DUK_DDDPRINT("created bound function: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
33392 
33393 	return 1;
33394 }
33395 #endif  /* DUK_USE_FUNCTION_BUILTIN */
33396 
33397 /* %NativeFunctionPrototype% .length getter. */
duk_bi_native_function_length(duk_hthread * thr)33398 DUK_INTERNAL duk_ret_t duk_bi_native_function_length(duk_hthread *thr) {
33399 	duk_tval *tv;
33400 	duk_hnatfunc *h;
33401 	duk_int16_t func_nargs;
33402 
33403 	tv = duk_get_borrowed_this_tval(thr);
33404 	DUK_ASSERT(tv != NULL);
33405 
33406 	if (DUK_TVAL_IS_OBJECT(tv)) {
33407 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33408 		DUK_ASSERT(h != NULL);
33409 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33410 			goto fail_type;
33411 		}
33412 		func_nargs = h->nargs;
33413 		duk_push_int(thr, func_nargs == DUK_HNATFUNC_NARGS_VARARGS ? 0 : func_nargs);
33414 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33415 		duk_small_uint_t lf_flags;
33416 		duk_small_uint_t lf_len;
33417 
33418 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv);
33419 		lf_len = DUK_LFUNC_FLAGS_GET_LENGTH(lf_flags);
33420 		duk_push_uint(thr, lf_len);
33421 	} else {
33422 		goto fail_type;
33423 	}
33424 	return 1;
33425 
33426  fail_type:
33427 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33428 }
33429 
33430 /* %NativeFunctionPrototype% .name getter. */
duk_bi_native_function_name(duk_hthread * thr)33431 DUK_INTERNAL duk_ret_t duk_bi_native_function_name(duk_hthread *thr) {
33432 	duk_tval *tv;
33433 	duk_hnatfunc *h;
33434 
33435 	tv = duk_get_borrowed_this_tval(thr);
33436 	DUK_ASSERT(tv != NULL);
33437 
33438 	if (DUK_TVAL_IS_OBJECT(tv)) {
33439 		h = (duk_hnatfunc *) DUK_TVAL_GET_OBJECT(tv);
33440 		DUK_ASSERT(h != NULL);
33441 		if (!DUK_HOBJECT_IS_NATFUNC((duk_hobject *) h)) {
33442 			goto fail_type;
33443 		}
33444 #if 0
33445 		duk_push_hnatfunc_name(thr, h);
33446 #endif
33447 		duk_push_hstring_empty(thr);
33448 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv)) {
33449 		duk_push_lightfunc_name(thr, tv);
33450 	} else {
33451 		goto fail_type;
33452 	}
33453 	return 1;
33454 
33455  fail_type:
33456 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
33457 }
33458 
33459 #if defined(DUK_USE_SYMBOL_BUILTIN)
duk_bi_function_prototype_hasinstance(duk_hthread * thr)33460 DUK_INTERNAL duk_ret_t duk_bi_function_prototype_hasinstance(duk_hthread *thr) {
33461 	/* This binding: RHS, stack index 0: LHS. */
33462 	duk_bool_t ret;
33463 
33464 	ret = duk_js_instanceof_ordinary(thr, DUK_GET_TVAL_POSIDX(thr, 0), DUK_GET_THIS_TVAL_PTR(thr));
33465 	duk_push_boolean(thr, ret);
33466 	return 1;
33467 }
33468 #endif  /* DUK_USE_SYMBOL_BUILTIN */
33469 #line 1 "duk_bi_global.c"
33470 /*
33471  *  Global object built-ins
33472  */
33473 
33474 /* #include duk_internal.h -> already included */
33475 
33476 /*
33477  *  Encoding/decoding helpers
33478  */
33479 
33480 /* XXX: Could add fast path (for each transform callback) with direct byte
33481  * lookups (no shifting) and no explicit check for x < 0x80 before table
33482  * lookup.
33483  */
33484 
33485 /* Macros for creating and checking bitmasks for character encoding.
33486  * Bit number is a bit counterintuitive, but minimizes code size.
33487  */
33488 #define DUK__MKBITS(a,b,c,d,e,f,g,h)  ((duk_uint8_t) ( \
33489 	((a) << 0) | ((b) << 1) | ((c) << 2) | ((d) << 3) | \
33490 	((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7) \
33491 	))
33492 #define DUK__CHECK_BITMASK(table,cp)  ((table)[(cp) >> 3] & (1 << ((cp) & 0x07)))
33493 
33494 /* E5.1 Section 15.1.3.3: uriReserved + uriUnescaped + '#' */
33495 DUK_LOCAL const duk_uint8_t duk__encode_uriunescaped_table[16] = {
33496 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33497 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33498 	DUK__MKBITS(0, 1, 0, 1, 1, 0, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x20-0x2f */
33499 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33500 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33501 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33502 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33503 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33504 };
33505 
33506 /* E5.1 Section 15.1.3.4: uriUnescaped */
33507 DUK_LOCAL const duk_uint8_t duk__encode_uricomponent_unescaped_table[16] = {
33508 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33509 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33510 	DUK__MKBITS(0, 1, 0, 0, 0, 0, 0, 1), DUK__MKBITS(1, 1, 1, 0, 0, 1, 1, 0),  /* 0x20-0x2f */
33511 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33512 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33513 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33514 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33515 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 1, 0),  /* 0x70-0x7f */
33516 };
33517 
33518 /* E5.1 Section 15.1.3.1: uriReserved + '#' */
33519 DUK_LOCAL const duk_uint8_t duk__decode_uri_reserved_table[16] = {
33520 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33521 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33522 	DUK__MKBITS(0, 0, 0, 1, 1, 0, 1, 0), DUK__MKBITS(0, 0, 0, 1, 1, 0, 0, 1),  /* 0x20-0x2f */
33523 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 0, 1),  /* 0x30-0x3f */
33524 	DUK__MKBITS(1, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33525 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33526 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33527 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33528 };
33529 
33530 /* E5.1 Section 15.1.3.2: empty */
33531 DUK_LOCAL const duk_uint8_t duk__decode_uri_component_reserved_table[16] = {
33532 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33533 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33534 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x20-0x2f */
33535 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33536 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x40-0x4f */
33537 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x50-0x5f */
33538 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x60-0x6f */
33539 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x70-0x7f */
33540 };
33541 
33542 #if defined(DUK_USE_SECTION_B)
33543 /* E5.1 Section B.2.2, step 7. */
33544 DUK_LOCAL const duk_uint8_t duk__escape_unescaped_table[16] = {
33545 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x00-0x0f */
33546 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0),  /* 0x10-0x1f */
33547 	DUK__MKBITS(0, 0, 0, 0, 0, 0, 0, 0), DUK__MKBITS(0, 0, 1, 1, 0, 1, 1, 1),  /* 0x20-0x2f */
33548 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 0, 0, 0, 0, 0, 0),  /* 0x30-0x3f */
33549 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x40-0x4f */
33550 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 1),  /* 0x50-0x5f */
33551 	DUK__MKBITS(0, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1),  /* 0x60-0x6f */
33552 	DUK__MKBITS(1, 1, 1, 1, 1, 1, 1, 1), DUK__MKBITS(1, 1, 1, 0, 0, 0, 0, 0)   /* 0x70-0x7f */
33553 };
33554 #endif  /* DUK_USE_SECTION_B */
33555 
33556 typedef struct {
33557 	duk_hthread *thr;
33558 	duk_hstring *h_str;
33559 	duk_bufwriter_ctx bw;
33560 	const duk_uint8_t *p;
33561 	const duk_uint8_t *p_start;
33562 	const duk_uint8_t *p_end;
33563 } duk__transform_context;
33564 
33565 typedef void (*duk__transform_callback)(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp);
33566 
33567 /* XXX: refactor and share with other code */
duk__decode_hex_escape(const duk_uint8_t * p,duk_small_int_t n)33568 DUK_LOCAL duk_small_int_t duk__decode_hex_escape(const duk_uint8_t *p, duk_small_int_t n) {
33569 	duk_small_int_t ch;
33570 	duk_small_int_t t = 0;
33571 
33572 	while (n > 0) {
33573 		t = t * 16;
33574 		ch = (duk_small_int_t) duk_hex_dectab[*p++];
33575 		if (DUK_LIKELY(ch >= 0)) {
33576 			t += ch;
33577 		} else {
33578 			return -1;
33579 		}
33580 		n--;
33581 	}
33582 	return t;
33583 }
33584 
duk__transform_helper(duk_hthread * thr,duk__transform_callback callback,const void * udata)33585 DUK_LOCAL int duk__transform_helper(duk_hthread *thr, duk__transform_callback callback, const void *udata) {
33586 	duk__transform_context tfm_ctx_alloc;
33587 	duk__transform_context *tfm_ctx = &tfm_ctx_alloc;
33588 	duk_codepoint_t cp;
33589 
33590 	tfm_ctx->thr = thr;
33591 
33592 	tfm_ctx->h_str = duk_to_hstring(thr, 0);
33593 	DUK_ASSERT(tfm_ctx->h_str != NULL);
33594 
33595 	DUK_BW_INIT_PUSHBUF(thr, &tfm_ctx->bw, DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str));  /* initial size guess */
33596 
33597 	tfm_ctx->p_start = DUK_HSTRING_GET_DATA(tfm_ctx->h_str);
33598 	tfm_ctx->p_end = tfm_ctx->p_start + DUK_HSTRING_GET_BYTELEN(tfm_ctx->h_str);
33599 	tfm_ctx->p = tfm_ctx->p_start;
33600 
33601 	while (tfm_ctx->p < tfm_ctx->p_end) {
33602 		cp = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end);
33603 		callback(tfm_ctx, udata, cp);
33604 	}
33605 
33606 	DUK_BW_COMPACT(thr, &tfm_ctx->bw);
33607 
33608 	(void) duk_buffer_to_string(thr, -1);  /* Safe if transform is safe. */
33609 	return 1;
33610 }
33611 
duk__transform_callback_encode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33612 DUK_LOCAL void duk__transform_callback_encode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33613 	duk_uint8_t xutf8_buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
33614 	duk_small_int_t len;
33615 	duk_codepoint_t cp1, cp2;
33616 	duk_small_int_t i, t;
33617 	const duk_uint8_t *unescaped_table = (const duk_uint8_t *) udata;
33618 
33619 	/* UTF-8 encoded bytes escaped as %xx%xx%xx... -> 3 * nbytes.
33620 	 * Codepoint range is restricted so this is a slightly too large
33621 	 * but doesn't matter.
33622 	 */
33623 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 3 * DUK_UNICODE_MAX_XUTF8_LENGTH);
33624 
33625 	if (cp < 0) {
33626 		goto uri_error;
33627 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(unescaped_table, cp)) {
33628 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33629 		return;
33630 	} else if (cp >= 0xdc00L && cp <= 0xdfffL) {
33631 		goto uri_error;
33632 	} else if (cp >= 0xd800L && cp <= 0xdbffL) {
33633 		/* Needs lookahead */
33634 		if (duk_unicode_decode_xutf8(tfm_ctx->thr, &tfm_ctx->p, tfm_ctx->p_start, tfm_ctx->p_end, (duk_ucodepoint_t *) &cp2) == 0) {
33635 			goto uri_error;
33636 		}
33637 		if (!(cp2 >= 0xdc00L && cp2 <= 0xdfffL)) {
33638 			goto uri_error;
33639 		}
33640 		cp1 = cp;
33641 		cp = (duk_codepoint_t) (((cp1 - 0xd800L) << 10) + (cp2 - 0xdc00L) + 0x10000L);
33642 	} else if (cp > 0x10ffffL) {
33643 		/* Although we can allow non-BMP characters (they'll decode
33644 		 * back into surrogate pairs), we don't allow extended UTF-8
33645 		 * characters; they would encode to URIs which won't decode
33646 		 * back because of strict UTF-8 checks in URI decoding.
33647 		 * (However, we could just as well allow them here.)
33648 		 */
33649 		goto uri_error;
33650 	} else {
33651 		/* Non-BMP characters within valid UTF-8 range: encode as is.
33652 		 * They'll decode back into surrogate pairs if the escaped
33653 		 * output is decoded.
33654 		 */
33655 		;
33656 	}
33657 
33658 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) cp, xutf8_buf);
33659 	for (i = 0; i < len; i++) {
33660 		t = (duk_small_int_t) xutf8_buf[i];
33661 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33662 		                      &tfm_ctx->bw,
33663 		                      DUK_ASC_PERCENT,
33664 		                      (duk_uint8_t) duk_uc_nybbles[t >> 4],
33665                                       (duk_uint8_t) duk_uc_nybbles[t & 0x0f]);
33666 	}
33667 
33668 	return;
33669 
33670  uri_error:
33671 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33672 	DUK_WO_NORETURN(return;);
33673 }
33674 
duk__transform_callback_decode_uri(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33675 DUK_LOCAL void duk__transform_callback_decode_uri(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33676 	const duk_uint8_t *reserved_table = (const duk_uint8_t *) udata;
33677 	duk_small_uint_t utf8_blen;
33678 	duk_codepoint_t min_cp;
33679 	duk_small_int_t t;  /* must be signed */
33680 	duk_small_uint_t i;
33681 
33682 	/* Maximum write size: XUTF8 path writes max DUK_UNICODE_MAX_XUTF8_LENGTH,
33683 	 * percent escape path writes max two times CESU-8 encoded BMP length.
33684 	 */
33685 	DUK_BW_ENSURE(tfm_ctx->thr,
33686 	              &tfm_ctx->bw,
33687 	              (DUK_UNICODE_MAX_XUTF8_LENGTH >= 2 * DUK_UNICODE_MAX_CESU8_BMP_LENGTH ?
33688 	              DUK_UNICODE_MAX_XUTF8_LENGTH : DUK_UNICODE_MAX_CESU8_BMP_LENGTH));
33689 
33690 	if (cp == (duk_codepoint_t) '%') {
33691 		const duk_uint8_t *p = tfm_ctx->p;
33692 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
33693 
33694 		DUK_DDD(DUK_DDDPRINT("percent encoding, left=%ld", (long) left));
33695 
33696 		if (left < 2) {
33697 			goto uri_error;
33698 		}
33699 
33700 		t = duk__decode_hex_escape(p, 2);
33701 		DUK_DDD(DUK_DDDPRINT("first byte: %ld", (long) t));
33702 		if (t < 0) {
33703 			goto uri_error;
33704 		}
33705 
33706 		if (t < 0x80) {
33707 			if (DUK__CHECK_BITMASK(reserved_table, t)) {
33708 				/* decode '%xx' to '%xx' if decoded char in reserved set */
33709 				DUK_ASSERT(tfm_ctx->p - 1 >= tfm_ctx->p_start);
33710 				DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33711 				                      &tfm_ctx->bw,
33712 				                      DUK_ASC_PERCENT,
33713 				                      p[0],
33714 				                      p[1]);
33715 			} else {
33716 				DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) t);
33717 			}
33718 			tfm_ctx->p += 2;
33719 			return;
33720 		}
33721 
33722 		/* Decode UTF-8 codepoint from a sequence of hex escapes.  The
33723 		 * first byte of the sequence has been decoded to 't'.
33724 		 *
33725 		 * Note that UTF-8 validation must be strict according to the
33726 		 * specification: E5.1 Section 15.1.3, decode algorithm step
33727 		 * 4.d.vii.8.  URIError from non-shortest encodings is also
33728 		 * specifically noted in the spec.
33729 		 */
33730 
33731 		DUK_ASSERT(t >= 0x80);
33732 		if (t < 0xc0) {
33733 			/* continuation byte */
33734 			goto uri_error;
33735 		} else if (t < 0xe0) {
33736 			/* 110x xxxx; 2 bytes */
33737 			utf8_blen = 2;
33738 			min_cp = 0x80L;
33739 			cp = t & 0x1f;
33740 		} else if (t < 0xf0) {
33741 			/* 1110 xxxx; 3 bytes */
33742 			utf8_blen = 3;
33743 			min_cp = 0x800L;
33744 			cp = t & 0x0f;
33745 		} else if (t < 0xf8) {
33746 			/* 1111 0xxx; 4 bytes */
33747 			utf8_blen = 4;
33748 			min_cp = 0x10000L;
33749 			cp = t & 0x07;
33750 		} else {
33751 			/* extended utf-8 not allowed for URIs */
33752 			goto uri_error;
33753 		}
33754 
33755 		if (left < utf8_blen * 3 - 1) {
33756 			/* '%xx%xx...%xx', p points to char after first '%' */
33757 			goto uri_error;
33758 		}
33759 
33760 		p += 3;
33761 		for (i = 1; i < utf8_blen; i++) {
33762 			/* p points to digit part ('%xy', p points to 'x') */
33763 			t = duk__decode_hex_escape(p, 2);
33764 			DUK_DDD(DUK_DDDPRINT("i=%ld utf8_blen=%ld cp=%ld t=0x%02lx",
33765 			                     (long) i, (long) utf8_blen, (long) cp, (unsigned long) t));
33766 			if (t < 0) {
33767 				goto uri_error;
33768 			}
33769 			if ((t & 0xc0) != 0x80) {
33770 				goto uri_error;
33771 			}
33772 			cp = (cp << 6) + (t & 0x3f);
33773 			p += 3;
33774 		}
33775 		p--;  /* p overshoots */
33776 		tfm_ctx->p = p;
33777 
33778 		DUK_DDD(DUK_DDDPRINT("final cp=%ld, min_cp=%ld", (long) cp, (long) min_cp));
33779 
33780 		if (cp < min_cp || cp > 0x10ffffL || (cp >= 0xd800L && cp <= 0xdfffL)) {
33781 			goto uri_error;
33782 		}
33783 
33784 		/* The E5.1 algorithm checks whether or not a decoded codepoint
33785 		 * is below 0x80 and perhaps may be in the "reserved" set.
33786 		 * This seems pointless because the single byte UTF-8 case is
33787 		 * handled separately, and non-shortest encodings are rejected.
33788 		 * So, 'cp' cannot be below 0x80 here, and thus cannot be in
33789 		 * the reserved set.
33790 		 */
33791 
33792 		/* utf-8 validation ensures these */
33793 		DUK_ASSERT(cp >= 0x80L && cp <= 0x10ffffL);
33794 
33795 		if (cp >= 0x10000L) {
33796 			cp -= 0x10000L;
33797 			DUK_ASSERT(cp < 0x100000L);
33798 
33799 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp >> 10) + 0xd800L));
33800 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, ((cp & 0x03ffL) + 0xdc00L));
33801 		} else {
33802 			DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33803 		}
33804 	} else {
33805 		DUK_BW_WRITE_RAW_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33806 	}
33807 	return;
33808 
33809  uri_error:
33810 	DUK_ERROR_URI(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33811 	DUK_WO_NORETURN(return;);
33812 }
33813 
33814 #if defined(DUK_USE_SECTION_B)
duk__transform_callback_escape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33815 DUK_LOCAL void duk__transform_callback_escape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33816 	DUK_UNREF(udata);
33817 
33818 	DUK_BW_ENSURE(tfm_ctx->thr, &tfm_ctx->bw, 6);
33819 
33820 	if (cp < 0) {
33821 		goto esc_error;
33822 	} else if ((cp < 0x80L) && DUK__CHECK_BITMASK(duk__escape_unescaped_table, cp)) {
33823 		DUK_BW_WRITE_RAW_U8(tfm_ctx->thr, &tfm_ctx->bw, (duk_uint8_t) cp);
33824 	} else if (cp < 0x100L) {
33825 		DUK_BW_WRITE_RAW_U8_3(tfm_ctx->thr,
33826 		                      &tfm_ctx->bw,
33827 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33828 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 4],
33829 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33830 	} else if (cp < 0x10000L) {
33831 		DUK_BW_WRITE_RAW_U8_6(tfm_ctx->thr,
33832 		                      &tfm_ctx->bw,
33833 		                      (duk_uint8_t) DUK_ASC_PERCENT,
33834 		                      (duk_uint8_t) DUK_ASC_LC_U,
33835 		                      (duk_uint8_t) duk_uc_nybbles[cp >> 12],
33836 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 8) & 0x0f],
33837 		                      (duk_uint8_t) duk_uc_nybbles[(cp >> 4) & 0x0f],
33838 		                      (duk_uint8_t) duk_uc_nybbles[cp & 0x0f]);
33839 	} else {
33840 		/* Characters outside BMP cannot be escape()'d.  We could
33841 		 * encode them as surrogate pairs (for codepoints inside
33842 		 * valid UTF-8 range, but not extended UTF-8).  Because
33843 		 * escape() and unescape() are legacy functions, we don't.
33844 		 */
33845 		goto esc_error;
33846 	}
33847 
33848 	return;
33849 
33850  esc_error:
33851 	DUK_ERROR_TYPE(tfm_ctx->thr, DUK_STR_INVALID_INPUT);
33852 	DUK_WO_NORETURN(return;);
33853 }
33854 
duk__transform_callback_unescape(duk__transform_context * tfm_ctx,const void * udata,duk_codepoint_t cp)33855 DUK_LOCAL void duk__transform_callback_unescape(duk__transform_context *tfm_ctx, const void *udata, duk_codepoint_t cp) {
33856 	duk_small_int_t t;
33857 
33858 	DUK_UNREF(udata);
33859 
33860 	if (cp == (duk_codepoint_t) '%') {
33861 		const duk_uint8_t *p = tfm_ctx->p;
33862 		duk_size_t left = (duk_size_t) (tfm_ctx->p_end - p);  /* bytes left */
33863 
33864 		if (left >= 5 && p[0] == 'u' &&
33865 		    ((t = duk__decode_hex_escape(p + 1, 4)) >= 0)) {
33866 			cp = (duk_codepoint_t) t;
33867 			tfm_ctx->p += 5;
33868 		} else if (left >= 2 &&
33869 		           ((t = duk__decode_hex_escape(p, 2)) >= 0)) {
33870 			cp = (duk_codepoint_t) t;
33871 			tfm_ctx->p += 2;
33872 		}
33873 	}
33874 
33875 	DUK_BW_WRITE_ENSURE_XUTF8(tfm_ctx->thr, &tfm_ctx->bw, cp);
33876 }
33877 #endif  /* DUK_USE_SECTION_B */
33878 
33879 /*
33880  *  Eval
33881  *
33882  *  Eval needs to handle both a "direct eval" and an "indirect eval".
33883  *  Direct eval handling needs access to the caller's activation so that its
33884  *  lexical environment can be accessed.  A direct eval is only possible from
33885  *  ECMAScript code; an indirect eval call is possible also from C code.
33886  *  When an indirect eval call is made from C code, there may not be a
33887  *  calling activation at all which needs careful handling.
33888  */
33889 
duk_bi_global_object_eval(duk_hthread * thr)33890 DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_hthread *thr) {
33891 	duk_hstring *h;
33892 	duk_activation *act_caller;
33893 	duk_activation *act_eval;
33894 	duk_hcompfunc *func;
33895 	duk_hobject *outer_lex_env;
33896 	duk_hobject *outer_var_env;
33897 	duk_bool_t this_to_global = 1;
33898 	duk_small_uint_t comp_flags;
33899 	duk_int_t level = -2;
33900 	duk_small_uint_t call_flags;
33901 
33902 	DUK_ASSERT(duk_get_top(thr) == 1 || duk_get_top(thr) == 2);  /* 2 when called by debugger */
33903 	DUK_ASSERT(thr->callstack_top >= 1);  /* at least this function exists */
33904 	DUK_ASSERT(thr->callstack_curr != NULL);
33905 	DUK_ASSERT((thr->callstack_curr->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0 || /* indirect eval */
33906 	           (thr->callstack_top >= 2));  /* if direct eval, calling activation must exist */
33907 
33908 	/*
33909 	 *  callstack_top - 1 --> this function
33910 	 *  callstack_top - 2 --> caller (may not exist)
33911 	 *
33912 	 *  If called directly from C, callstack_top might be 1.  If calling
33913 	 *  activation doesn't exist, call must be indirect.
33914 	 */
33915 
33916 	h = duk_get_hstring_notsymbol(thr, 0);
33917 	if (!h) {
33918 		/* Symbol must be returned as is, like any non-string values. */
33919 		return 1;  /* return arg as-is */
33920 	}
33921 
33922 #if defined(DUK_USE_DEBUGGER_SUPPORT)
33923 	/* NOTE: level is used only by the debugger and should never be present
33924 	 * for an ECMAScript eval().
33925 	 */
33926 	DUK_ASSERT(level == -2);  /* by default, use caller's environment */
33927 	if (duk_get_top(thr) >= 2 && duk_is_number(thr, 1)) {
33928 		level = duk_get_int(thr, 1);
33929 	}
33930 	DUK_ASSERT(level <= -2);  /* This is guaranteed by debugger code. */
33931 #endif
33932 
33933 	/* [ source ] */
33934 
33935 	comp_flags = DUK_COMPILE_EVAL;
33936 	act_eval = thr->callstack_curr;  /* this function */
33937 	DUK_ASSERT(act_eval != NULL);
33938 	act_caller = duk_hthread_get_activation_for_level(thr, level);
33939 	if (act_caller != NULL) {
33940 		/* Have a calling activation, check for direct eval (otherwise
33941 		 * assume indirect eval.
33942 		 */
33943 		if ((act_caller->flags & DUK_ACT_FLAG_STRICT) &&
33944 		    (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL)) {
33945 			/* Only direct eval inherits strictness from calling code
33946 			 * (E5.1 Section 10.1.1).
33947 			 */
33948 			comp_flags |= DUK_COMPILE_STRICT;
33949 		}
33950 	} else {
33951 		DUK_ASSERT((act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) == 0);
33952 	}
33953 
33954 	duk_push_hstring_stridx(thr, DUK_STRIDX_INPUT);  /* XXX: copy from caller? */
33955 	duk_js_compile(thr,
33956 	               (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h),
33957 	               (duk_size_t) DUK_HSTRING_GET_BYTELEN(h),
33958 	               comp_flags);
33959 	func = (duk_hcompfunc *) duk_known_hobject(thr, -1);
33960 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) func));
33961 
33962 	/* [ source template ] */
33963 
33964 	/* E5 Section 10.4.2 */
33965 
33966 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
33967 		DUK_ASSERT(thr->callstack_top >= 2);
33968 		DUK_ASSERT(act_caller != NULL);
33969 		if (act_caller->lex_env == NULL) {
33970 			DUK_ASSERT(act_caller->var_env == NULL);
33971 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
33972 
33973 			/* this may have side effects, so re-lookup act */
33974 			duk_js_init_activation_environment_records_delayed(thr, act_caller);
33975 		}
33976 		DUK_ASSERT(act_caller->lex_env != NULL);
33977 		DUK_ASSERT(act_caller->var_env != NULL);
33978 
33979 		this_to_global = 0;
33980 
33981 		if (DUK_HOBJECT_HAS_STRICT((duk_hobject *) func)) {
33982 			duk_hdecenv *new_env;
33983 			duk_hobject *act_lex_env;
33984 
33985 			DUK_DDD(DUK_DDDPRINT("direct eval call to a strict function -> "
33986 			                     "var_env and lex_env to a fresh env, "
33987 			                     "this_binding to caller's this_binding"));
33988 
33989 			act_lex_env = act_caller->lex_env;
33990 
33991 			new_env = duk_hdecenv_alloc(thr,
33992 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
33993 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
33994 			DUK_ASSERT(new_env != NULL);
33995 			duk_push_hobject(thr, (duk_hobject *) new_env);
33996 
33997 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
33998 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act_lex_env);
33999 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, act_lex_env);
34000 			DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
34001 
34002 			outer_lex_env = (duk_hobject *) new_env;
34003 			outer_var_env = (duk_hobject *) new_env;
34004 
34005 			duk_insert(thr, 0);  /* stash to bottom of value stack to keep new_env reachable for duration of eval */
34006 
34007 			/* compiler's responsibility */
34008 			DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34009 		} else {
34010 			DUK_DDD(DUK_DDDPRINT("direct eval call to a non-strict function -> "
34011 			                     "var_env and lex_env to caller's envs, "
34012 			                     "this_binding to caller's this_binding"));
34013 
34014 			outer_lex_env = act_caller->lex_env;
34015 			outer_var_env = act_caller->var_env;
34016 
34017 			/* compiler's responsibility */
34018 			DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) func));
34019 		}
34020 	} else {
34021 		DUK_DDD(DUK_DDDPRINT("indirect eval call -> var_env and lex_env to "
34022 		                     "global object, this_binding to global object"));
34023 
34024 		this_to_global = 1;
34025 		outer_lex_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34026 		outer_var_env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
34027 	}
34028 
34029 	/* Eval code doesn't need an automatic .prototype object. */
34030 	duk_js_push_closure(thr, func, outer_var_env, outer_lex_env, 0 /*add_auto_proto*/);
34031 
34032 	/* [ env? source template closure ] */
34033 
34034 	if (this_to_global) {
34035 		DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
34036 		duk_push_hobject_bidx(thr, DUK_BIDX_GLOBAL);
34037 	} else {
34038 		duk_tval *tv;
34039 		DUK_ASSERT(thr->callstack_top >= 2);
34040 		DUK_ASSERT(act_caller != NULL);
34041 		tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act_caller->bottom_byteoff - sizeof(duk_tval));  /* this is just beneath bottom */
34042 		DUK_ASSERT(tv >= thr->valstack);
34043 		duk_push_tval(thr, tv);
34044 	}
34045 
34046 	DUK_DDD(DUK_DDDPRINT("eval -> lex_env=%!iO, var_env=%!iO, this_binding=%!T",
34047 	                     (duk_heaphdr *) outer_lex_env,
34048 	                     (duk_heaphdr *) outer_var_env,
34049 	                     duk_get_tval(thr, -1)));
34050 
34051 	/* [ env? source template closure this ] */
34052 
34053 	call_flags = 0;
34054 	if (act_eval->flags & DUK_ACT_FLAG_DIRECT_EVAL) {
34055 		/* Set DIRECT_EVAL flag for the call; it's not strictly
34056 		 * needed for the 'inner' eval call (the eval body) but
34057 		 * current new.target implementation expects to find it
34058 		 * so it can traverse direct eval chains up to the real
34059 		 * calling function.
34060 		 */
34061 		call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
34062 	}
34063 	duk_handle_call_unprotected_nargs(thr, 0, call_flags);
34064 
34065 	/* [ env? source template result ] */
34066 
34067 	return 1;
34068 }
34069 
34070 /*
34071  *  Parsing of ints and floats
34072  */
34073 
34074 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_int(duk_hthread * thr)34075 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_int(duk_hthread *thr) {
34076 	duk_int32_t radix;
34077 	duk_small_uint_t s2n_flags;
34078 
34079 	DUK_ASSERT_TOP(thr, 2);
34080 	duk_to_string(thr, 0);  /* Reject symbols. */
34081 
34082 	radix = duk_to_int32(thr, 1);
34083 
34084 	/* While parseInt() recognizes 0xdeadbeef, it doesn't recognize
34085 	 * ES2015 0o123 or 0b10001.
34086 	 */
34087 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34088 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34089 	            DUK_S2N_FLAG_ALLOW_PLUS |
34090 	            DUK_S2N_FLAG_ALLOW_MINUS |
34091 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
34092 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34093 
34094 	/* Specification stripPrefix maps to DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT.
34095 	 *
34096 	 * Don't autodetect octals (from leading zeroes), require user code to
34097 	 * provide an explicit radix 8 for parsing octal.  See write-up from Mozilla:
34098 	 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_Removes_Octal_Interpretation
34099 	 */
34100 
34101 	if (radix != 0) {
34102 		if (radix < 2 || radix > 36) {
34103 			goto ret_nan;
34104 		}
34105 		if (radix != 16) {
34106 			s2n_flags &= ~DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT;
34107 		}
34108 	} else {
34109 		radix = 10;
34110 	}
34111 
34112 	duk_dup_0(thr);
34113 	duk_numconv_parse(thr, (duk_small_int_t) radix, s2n_flags);
34114 	return 1;
34115 
34116  ret_nan:
34117 	duk_push_nan(thr);
34118 	return 1;
34119 }
34120 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34121 
34122 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_parse_float(duk_hthread * thr)34123 DUK_INTERNAL duk_ret_t duk_bi_global_object_parse_float(duk_hthread *thr) {
34124 	duk_small_uint_t s2n_flags;
34125 
34126 	DUK_ASSERT_TOP(thr, 1);
34127 	duk_to_string(thr, 0);  /* Reject symbols. */
34128 
34129 	/* XXX: check flags */
34130 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
34131 	            DUK_S2N_FLAG_ALLOW_EXP |
34132 	            DUK_S2N_FLAG_ALLOW_GARBAGE |
34133 	            DUK_S2N_FLAG_ALLOW_PLUS |
34134 	            DUK_S2N_FLAG_ALLOW_MINUS |
34135 	            DUK_S2N_FLAG_ALLOW_INF |
34136 	            DUK_S2N_FLAG_ALLOW_FRAC |
34137 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
34138 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
34139 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
34140 
34141 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
34142 	return 1;
34143 }
34144 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34145 
34146 /*
34147  *  Number checkers
34148  */
34149 
34150 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_nan(duk_hthread * thr)34151 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_nan(duk_hthread *thr) {
34152 	duk_double_t d = duk_to_number(thr, 0);
34153 	duk_push_boolean(thr, (duk_bool_t) DUK_ISNAN(d));
34154 	return 1;
34155 }
34156 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34157 
34158 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_is_finite(duk_hthread * thr)34159 DUK_INTERNAL duk_ret_t duk_bi_global_object_is_finite(duk_hthread *thr) {
34160 	duk_double_t d = duk_to_number(thr, 0);
34161 	duk_push_boolean(thr, (duk_bool_t) DUK_ISFINITE(d));
34162 	return 1;
34163 }
34164 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34165 
34166 /*
34167  *  URI handling
34168  */
34169 
34170 #if defined(DUK_USE_GLOBAL_BUILTIN)
duk_bi_global_object_decode_uri(duk_hthread * thr)34171 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri(duk_hthread *thr) {
34172 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_reserved_table);
34173 }
34174 
duk_bi_global_object_decode_uri_component(duk_hthread * thr)34175 DUK_INTERNAL duk_ret_t duk_bi_global_object_decode_uri_component(duk_hthread *thr) {
34176 	return duk__transform_helper(thr, duk__transform_callback_decode_uri, (const void *) duk__decode_uri_component_reserved_table);
34177 }
34178 
duk_bi_global_object_encode_uri(duk_hthread * thr)34179 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri(duk_hthread *thr) {
34180 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uriunescaped_table);
34181 }
34182 
duk_bi_global_object_encode_uri_component(duk_hthread * thr)34183 DUK_INTERNAL duk_ret_t duk_bi_global_object_encode_uri_component(duk_hthread *thr) {
34184 	return duk__transform_helper(thr, duk__transform_callback_encode_uri, (const void *) duk__encode_uricomponent_unescaped_table);
34185 }
34186 
34187 #if defined(DUK_USE_SECTION_B)
duk_bi_global_object_escape(duk_hthread * thr)34188 DUK_INTERNAL duk_ret_t duk_bi_global_object_escape(duk_hthread *thr) {
34189 	return duk__transform_helper(thr, duk__transform_callback_escape, (const void *) NULL);
34190 }
34191 
duk_bi_global_object_unescape(duk_hthread * thr)34192 DUK_INTERNAL duk_ret_t duk_bi_global_object_unescape(duk_hthread *thr) {
34193 	return duk__transform_helper(thr, duk__transform_callback_unescape, (const void *) NULL);
34194 }
34195 #endif  /* DUK_USE_SECTION_B */
34196 #endif  /* DUK_USE_GLOBAL_BUILTIN */
34197 
34198 /* automatic undefs */
34199 #undef DUK__CHECK_BITMASK
34200 #undef DUK__MKBITS
34201 #line 1 "duk_bi_json.c"
34202 /*
34203  *  JSON built-ins.
34204  *
34205  *  See doc/json.rst.
34206  *
34207  *  Codepoints are handled as duk_uint_fast32_t to ensure that the full
34208  *  unsigned 32-bit range is supported.  This matters to e.g. JX.
34209  *
34210  *  Input parsing doesn't do an explicit end-of-input check at all.  This is
34211  *  safe: input string data is always NUL-terminated (0x00) and valid JSON
34212  *  inputs never contain plain NUL characters, so that as long as syntax checks
34213  *  are correct, we'll never read past the NUL.  This approach reduces code size
34214  *  and improves parsing performance, but it's critical that syntax checks are
34215  *  indeed correct!
34216  */
34217 
34218 /* #include duk_internal.h -> already included */
34219 
34220 #if defined(DUK_USE_JSON_SUPPORT)
34221 
34222 /*
34223  *  Local defines and forward declarations.
34224  */
34225 
34226 #define DUK__JSON_DECSTR_BUFSIZE 128
34227 #define DUK__JSON_DECSTR_CHUNKSIZE 64
34228 #define DUK__JSON_ENCSTR_CHUNKSIZE 64
34229 #define DUK__JSON_STRINGIFY_BUFSIZE 128
34230 #define DUK__JSON_MAX_ESC_LEN 10  /* '\Udeadbeef' */
34231 
34232 DUK_LOCAL_DECL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx);
34233 DUK_LOCAL_DECL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx);
34234 #if defined(DUK_USE_JX)
34235 DUK_LOCAL_DECL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx);
34236 #endif
34237 DUK_LOCAL_DECL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx);
34238 DUK_LOCAL_DECL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx);
34239 DUK_LOCAL_DECL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n);
34240 DUK_LOCAL_DECL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx);
34241 DUK_LOCAL_DECL void duk__dec_string(duk_json_dec_ctx *js_ctx);
34242 #if defined(DUK_USE_JX)
34243 DUK_LOCAL_DECL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx);
34244 DUK_LOCAL_DECL void duk__dec_pointer(duk_json_dec_ctx *js_ctx);
34245 DUK_LOCAL_DECL void duk__dec_buffer(duk_json_dec_ctx *js_ctx);
34246 #endif
34247 DUK_LOCAL_DECL void duk__dec_number(duk_json_dec_ctx *js_ctx);
34248 DUK_LOCAL_DECL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx);
34249 DUK_LOCAL_DECL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx);
34250 DUK_LOCAL_DECL void duk__dec_object(duk_json_dec_ctx *js_ctx);
34251 DUK_LOCAL_DECL void duk__dec_array(duk_json_dec_ctx *js_ctx);
34252 DUK_LOCAL_DECL void duk__dec_value(duk_json_dec_ctx *js_ctx);
34253 DUK_LOCAL_DECL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx);
34254 
34255 DUK_LOCAL_DECL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch);
34256 DUK_LOCAL_DECL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2);
34257 DUK_LOCAL_DECL void duk__unemit_1(duk_json_enc_ctx *js_ctx);
34258 DUK_LOCAL_DECL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h);
34259 #if defined(DUK_USE_FASTINT)
34260 DUK_LOCAL_DECL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *p);
34261 #endif
34262 DUK_LOCAL_DECL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx);
34263 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);
34264 DUK_LOCAL_DECL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k);
34265 DUK_LOCAL_DECL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str);
34266 DUK_LOCAL_DECL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34267 DUK_LOCAL_DECL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top);
34268 DUK_LOCAL_DECL void duk__enc_object(duk_json_enc_ctx *js_ctx);
34269 DUK_LOCAL_DECL void duk__enc_array(duk_json_enc_ctx *js_ctx);
34270 DUK_LOCAL_DECL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder);
34271 DUK_LOCAL_DECL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv);
34272 DUK_LOCAL_DECL void duk__enc_double(duk_json_enc_ctx *js_ctx);
34273 #if defined(DUK_USE_FASTINT)
34274 DUK_LOCAL_DECL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv);
34275 #endif
34276 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
34277 DUK_LOCAL_DECL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34278 DUK_LOCAL_DECL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr);
34279 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
34280 DUK_LOCAL_DECL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj);
34281 #endif
34282 #endif
34283 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
34284 DUK_LOCAL_DECL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h);
34285 #endif
34286 DUK_LOCAL_DECL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth);
34287 
34288 /*
34289  *  Helper tables
34290  */
34291 
34292 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
34293 DUK_LOCAL const duk_uint8_t duk__json_quotestr_lookup[256] = {
34294 	/* 0x00 ... 0x7f: as is
34295 	 * 0x80: escape generically
34296 	 * 0x81: slow path
34297 	 * 0xa0 ... 0xff: backslash + one char
34298 	 */
34299 
34300 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xe2, 0xf4, 0xee, 0x80, 0xe6, 0xf2, 0x80, 0x80,
34301 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
34302 	0x20, 0x21, 0xa2, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34303 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34304 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34305 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0xdc, 0x5d, 0x5e, 0x5f,
34306 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34307 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x81,
34308 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34309 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34310 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34311 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34312 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34313 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34314 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
34315 	0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81
34316 };
34317 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34318 DUK_LOCAL const duk_uint8_t duk__json_quotestr_esc[14] = {
34319 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34320 	DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL, DUK_ASC_NUL,
34321 	DUK_ASC_LC_B, DUK_ASC_LC_T, DUK_ASC_LC_N, DUK_ASC_NUL,
34322 	DUK_ASC_LC_F, DUK_ASC_LC_R
34323 };
34324 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
34325 
34326 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34327 DUK_LOCAL const duk_uint8_t duk__json_decstr_lookup[256] = {
34328 	/* 0x00: slow path
34329 	 * other: as is
34330 	 */
34331 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34332 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34333 	0x20, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
34334 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
34335 	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
34336 	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x5d, 0x5e, 0x5f,
34337 	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
34338 	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
34339 	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
34340 	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
34341 	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
34342 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
34343 	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
34344 	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
34345 	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
34346 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
34347 };
34348 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34349 
34350 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34351 DUK_LOCAL const duk_uint8_t duk__json_eatwhite_lookup[256] = {
34352 	/* 0x00: finish (non-white)
34353 	 * 0x01: continue
34354 	 */
34355 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
34356 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34357 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34358 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34359 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34360 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34361 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34362 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34363 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34364 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34365 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34366 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34367 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34368 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34369 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34370 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34371 };
34372 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34373 
34374 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
34375 DUK_LOCAL const duk_uint8_t duk__json_decnumber_lookup[256] = {
34376 	/* 0x00: finish (not part of number)
34377 	 * 0x01: continue
34378 	 */
34379 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34380 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34381 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
34382 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34383 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34384 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34385 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34386 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34387 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34388 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34389 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34390 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34391 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34392 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34393 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34394 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34395 };
34396 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34397 
34398 /*
34399  *  Parsing implementation.
34400  *
34401  *  JSON lexer is now separate from duk_lexer.c because there are numerous
34402  *  small differences making it difficult to share the lexer.
34403  *
34404  *  The parser here works with raw bytes directly; this works because all
34405  *  JSON delimiters are ASCII characters.  Invalid xUTF-8 encoded values
34406  *  inside strings will be passed on without normalization; this is not a
34407  *  compliance concern because compliant inputs will always be valid
34408  *  CESU-8 encodings.
34409  */
34410 
duk__dec_syntax_error(duk_json_dec_ctx * js_ctx)34411 DUK_LOCAL void duk__dec_syntax_error(duk_json_dec_ctx *js_ctx) {
34412 	/* Shared handler to minimize parser size.  Cause will be
34413 	 * hidden, unfortunately, but we'll have an offset which
34414 	 * is often quite enough.
34415 	 */
34416 	DUK_ERROR_FMT1(js_ctx->thr, DUK_ERR_SYNTAX_ERROR, DUK_STR_FMT_INVALID_JSON,
34417 	               (long) (js_ctx->p - js_ctx->p_start));
34418 	DUK_WO_NORETURN(return;);
34419 }
34420 
duk__dec_eat_white(duk_json_dec_ctx * js_ctx)34421 DUK_LOCAL void duk__dec_eat_white(duk_json_dec_ctx *js_ctx) {
34422 	const duk_uint8_t *p;
34423 	duk_uint8_t t;
34424 
34425 	p = js_ctx->p;
34426 	for (;;) {
34427 		DUK_ASSERT(p <= js_ctx->p_end);
34428 		t = *p;
34429 
34430 #if defined(DUK_USE_JSON_EATWHITE_FASTPATH)
34431 		/* This fast path is pretty marginal in practice.
34432 		 * XXX: candidate for removal.
34433 		 */
34434 		DUK_ASSERT(duk__json_eatwhite_lookup[0x00] == 0x00);  /* end-of-input breaks */
34435 		if (duk__json_eatwhite_lookup[t] == 0) {
34436 			break;
34437 		}
34438 #else  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34439 		if (!(t == 0x20 || t == 0x0a || t == 0x0d || t == 0x09)) {
34440 			/* NUL also comes here.  Comparison order matters, 0x20
34441 			 * is most common whitespace.
34442 			 */
34443 			break;
34444 		}
34445 #endif  /* DUK_USE_JSON_EATWHITE_FASTPATH */
34446 		p++;
34447 	}
34448 	js_ctx->p = p;
34449 }
34450 
34451 #if defined(DUK_USE_JX)
duk__dec_peek(duk_json_dec_ctx * js_ctx)34452 DUK_LOCAL duk_uint8_t duk__dec_peek(duk_json_dec_ctx *js_ctx) {
34453 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34454 	return *js_ctx->p;
34455 }
34456 #endif
34457 
duk__dec_get(duk_json_dec_ctx * js_ctx)34458 DUK_LOCAL duk_uint8_t duk__dec_get(duk_json_dec_ctx *js_ctx) {
34459 	DUK_ASSERT(js_ctx->p <= js_ctx->p_end);
34460 	return *js_ctx->p++;
34461 }
34462 
duk__dec_get_nonwhite(duk_json_dec_ctx * js_ctx)34463 DUK_LOCAL duk_uint8_t duk__dec_get_nonwhite(duk_json_dec_ctx *js_ctx) {
34464 	duk__dec_eat_white(js_ctx);
34465 	return duk__dec_get(js_ctx);
34466 }
34467 
34468 /* 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)34469 DUK_LOCAL duk_uint_fast32_t duk__dec_decode_hex_escape(duk_json_dec_ctx *js_ctx, duk_small_uint_t n) {
34470 	duk_small_uint_t i;
34471 	duk_uint_fast32_t res = 0;
34472 	duk_uint8_t x;
34473 	duk_small_int_t t;
34474 
34475 	for (i = 0; i < n; i++) {
34476 		/* XXX: share helper from lexer; duk_lexer.c / hexval(). */
34477 
34478 		x = duk__dec_get(js_ctx);
34479 		DUK_DDD(DUK_DDDPRINT("decode_hex_escape: i=%ld, n=%ld, res=%ld, x=%ld",
34480 		                     (long) i, (long) n, (long) res, (long) x));
34481 
34482 		/* x == 0x00 (EOF) causes syntax_error */
34483 		DUK_ASSERT(duk_hex_dectab[0] == -1);
34484 		t = duk_hex_dectab[x & 0xff];
34485 		if (DUK_LIKELY(t >= 0)) {
34486 			res = (res * 16) + (duk_uint_fast32_t) t;
34487 		} else {
34488 			/* catches EOF and invalid digits */
34489 			goto syntax_error;
34490 		}
34491 	}
34492 
34493 	DUK_DDD(DUK_DDDPRINT("final hex decoded value: %ld", (long) res));
34494 	return res;
34495 
34496  syntax_error:
34497 	duk__dec_syntax_error(js_ctx);
34498 	DUK_UNREACHABLE();
34499 	return 0;
34500 }
34501 
duk__dec_req_stridx(duk_json_dec_ctx * js_ctx,duk_small_uint_t stridx)34502 DUK_LOCAL void duk__dec_req_stridx(duk_json_dec_ctx *js_ctx, duk_small_uint_t stridx) {
34503 	duk_hstring *h;
34504 	const duk_uint8_t *p;
34505 	duk_uint8_t x, y;
34506 
34507 	/* First character has already been eaten and checked by the caller.
34508 	 * We can scan until a NUL in stridx string because no built-in strings
34509 	 * have internal NULs.
34510 	 */
34511 
34512 	DUK_ASSERT_STRIDX_VALID(stridx);
34513 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
34514 	DUK_ASSERT(h != NULL);
34515 
34516 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h) + 1;
34517 	DUK_ASSERT(*(js_ctx->p - 1) == *(p - 1));  /* first character has been matched */
34518 
34519 	for (;;) {
34520 		x = *p;
34521 		if (x == 0) {
34522 			break;
34523 		}
34524 		y = duk__dec_get(js_ctx);
34525 		if (x != y) {
34526 			/* Catches EOF of JSON input. */
34527 			goto syntax_error;
34528 		}
34529 		p++;
34530 	}
34531 
34532 	return;
34533 
34534  syntax_error:
34535 	duk__dec_syntax_error(js_ctx);
34536 	DUK_UNREACHABLE();
34537 }
34538 
duk__dec_string_escape(duk_json_dec_ctx * js_ctx,duk_uint8_t ** ext_p)34539 DUK_LOCAL duk_small_int_t duk__dec_string_escape(duk_json_dec_ctx *js_ctx, duk_uint8_t **ext_p) {
34540 	duk_uint_fast32_t cp;
34541 
34542 	/* EOF (-1) will be cast to an unsigned value first
34543 	 * and then re-cast for the switch.  In any case, it
34544 	 * will match the default case (syntax error).
34545 	 */
34546 	cp = (duk_uint_fast32_t) duk__dec_get(js_ctx);
34547 	switch (cp) {
34548 	case DUK_ASC_BACKSLASH: break;
34549 	case DUK_ASC_DOUBLEQUOTE: break;
34550 	case DUK_ASC_SLASH: break;
34551 	case DUK_ASC_LC_T: cp = 0x09; break;
34552 	case DUK_ASC_LC_N: cp = 0x0a; break;
34553 	case DUK_ASC_LC_R: cp = 0x0d; break;
34554 	case DUK_ASC_LC_F: cp = 0x0c; break;
34555 	case DUK_ASC_LC_B: cp = 0x08; break;
34556 	case DUK_ASC_LC_U: {
34557 		cp = duk__dec_decode_hex_escape(js_ctx, 4);
34558 		break;
34559 	}
34560 #if defined(DUK_USE_JX)
34561 	case DUK_ASC_UC_U: {
34562 		if (js_ctx->flag_ext_custom) {
34563 			cp = duk__dec_decode_hex_escape(js_ctx, 8);
34564 		} else {
34565 			return 1;  /* syntax error */
34566 		}
34567 		break;
34568 	}
34569 	case DUK_ASC_LC_X: {
34570 		if (js_ctx->flag_ext_custom) {
34571 			cp = duk__dec_decode_hex_escape(js_ctx, 2);
34572 		} else {
34573 			return 1;  /* syntax error */
34574 		}
34575 		break;
34576 	}
34577 #endif  /* DUK_USE_JX */
34578 	default:
34579 		/* catches EOF (0x00) */
34580 		return 1;  /* syntax error */
34581 	}
34582 
34583 	DUK_RAW_WRITE_XUTF8(*ext_p, cp);
34584 
34585 	return 0;
34586 }
34587 
duk__dec_string(duk_json_dec_ctx * js_ctx)34588 DUK_LOCAL void duk__dec_string(duk_json_dec_ctx *js_ctx) {
34589 	duk_hthread *thr = js_ctx->thr;
34590 	duk_bufwriter_ctx bw_alloc;
34591 	duk_bufwriter_ctx *bw;
34592 	duk_uint8_t *q;
34593 
34594 	/* '"' was eaten by caller */
34595 
34596 	/* Note that we currently parse -bytes-, not codepoints.
34597 	 * All non-ASCII extended UTF-8 will encode to bytes >= 0x80,
34598 	 * so they'll simply pass through (valid UTF-8 or not).
34599 	 */
34600 
34601 	bw = &bw_alloc;
34602 	DUK_BW_INIT_PUSHBUF(js_ctx->thr, bw, DUK__JSON_DECSTR_BUFSIZE);
34603 	q = DUK_BW_GET_PTR(js_ctx->thr, bw);
34604 
34605 #if defined(DUK_USE_JSON_DECSTRING_FASTPATH)
34606 	for (;;) {
34607 		duk_small_uint_t safe;
34608 		duk_uint8_t b, x;
34609 		const duk_uint8_t *p;
34610 
34611 		/* Select a safe loop count where no output checks are
34612 		 * needed assuming we won't encounter escapes.  Input
34613 		 * bound checks are not necessary as a NUL (guaranteed)
34614 		 * will cause a SyntaxError before we read out of bounds.
34615 		 */
34616 
34617 		safe = DUK__JSON_DECSTR_CHUNKSIZE;
34618 
34619 		/* Ensure space for 1:1 output plus one escape. */
34620 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, safe + DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34621 
34622 		p = js_ctx->p;  /* temp copy, write back for next loop */
34623 		for (;;) {
34624 			if (safe == 0) {
34625 				js_ctx->p = p;
34626 				break;
34627 			}
34628 			safe--;
34629 
34630 			/* End of input (NUL) goes through slow path and causes SyntaxError. */
34631 			DUK_ASSERT(duk__json_decstr_lookup[0] == 0x00);
34632 
34633 			b = *p++;
34634 			x = (duk_small_int_t) duk__json_decstr_lookup[b];
34635 			if (DUK_LIKELY(x != 0)) {
34636 				/* Fast path, decode as is. */
34637 				*q++ = b;
34638 			} else if (b == DUK_ASC_DOUBLEQUOTE) {
34639 				js_ctx->p = p;
34640 				goto found_quote;
34641 			} else if (b == DUK_ASC_BACKSLASH) {
34642 				/* We've ensured space for one escaped input; then
34643 				 * bail out and recheck (this makes escape handling
34644 				 * quite slow but it's uncommon).
34645 				 */
34646 				js_ctx->p = p;
34647 				if (duk__dec_string_escape(js_ctx, &q) != 0) {
34648 					goto syntax_error;
34649 				}
34650 				break;
34651 			} else {
34652 				js_ctx->p = p;
34653 				goto syntax_error;
34654 			}
34655 		}
34656 	}
34657  found_quote:
34658 #else  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34659 	for (;;) {
34660 		duk_uint8_t x;
34661 
34662 		q = DUK_BW_ENSURE_RAW(js_ctx->thr, bw, DUK_UNICODE_MAX_XUTF8_LENGTH, q);
34663 
34664 		x = duk__dec_get(js_ctx);
34665 
34666 		if (x == DUK_ASC_DOUBLEQUOTE) {
34667 			break;
34668 		} else if (x == DUK_ASC_BACKSLASH) {
34669 			if (duk__dec_string_escape(js_ctx, &q) != 0) {
34670 				goto syntax_error;
34671 			}
34672 		} else if (x < 0x20) {
34673 			/* catches EOF (NUL) */
34674 			goto syntax_error;
34675 		} else {
34676 			*q++ = (duk_uint8_t) x;
34677 		}
34678 	}
34679 #endif  /* DUK_USE_JSON_DECSTRING_FASTPATH */
34680 
34681 	DUK_BW_SETPTR_AND_COMPACT(js_ctx->thr, bw, q);
34682 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input string is safe. */
34683 
34684 	/* [ ... str ] */
34685 
34686 	return;
34687 
34688  syntax_error:
34689 	duk__dec_syntax_error(js_ctx);
34690 	DUK_UNREACHABLE();
34691 }
34692 
34693 #if defined(DUK_USE_JX)
34694 /* Decode a plain string consisting entirely of identifier characters.
34695  * Used to parse plain keys (e.g. "foo: 123").
34696  */
duk__dec_plain_string(duk_json_dec_ctx * js_ctx)34697 DUK_LOCAL void duk__dec_plain_string(duk_json_dec_ctx *js_ctx) {
34698 	duk_hthread *thr = js_ctx->thr;
34699 	const duk_uint8_t *p;
34700 	duk_small_int_t x;
34701 
34702 	/* Caller has already eaten the first char so backtrack one byte. */
34703 
34704 	js_ctx->p--;  /* safe */
34705 	p = js_ctx->p;
34706 
34707 	/* Here again we parse bytes, and non-ASCII UTF-8 will cause end of
34708 	 * parsing (which is correct except if there are non-shortest encodings).
34709 	 * There is also no need to check explicitly for end of input buffer as
34710 	 * the input is NUL padded and NUL will exit the parsing loop.
34711 	 *
34712 	 * Because no unescaping takes place, we can just scan to the end of the
34713 	 * plain string and intern from the input buffer.
34714 	 */
34715 
34716 	for (;;) {
34717 		x = *p;
34718 
34719 		/* There is no need to check the first character specially here
34720 		 * (i.e. reject digits): the caller only accepts valid initial
34721 		 * characters and won't call us if the first character is a digit.
34722 		 * This also ensures that the plain string won't be empty.
34723 		 */
34724 
34725 		if (!duk_unicode_is_identifier_part((duk_codepoint_t) x)) {
34726 			break;
34727 		}
34728 		p++;
34729 	}
34730 
34731 	duk_push_lstring(thr, (const char *) js_ctx->p, (duk_size_t) (p - js_ctx->p));
34732 	js_ctx->p = p;
34733 
34734 	/* [ ... str ] */
34735 }
34736 #endif  /* DUK_USE_JX */
34737 
34738 #if defined(DUK_USE_JX)
duk__dec_pointer(duk_json_dec_ctx * js_ctx)34739 DUK_LOCAL void duk__dec_pointer(duk_json_dec_ctx *js_ctx) {
34740 	duk_hthread *thr = js_ctx->thr;
34741 	const duk_uint8_t *p;
34742 	duk_small_int_t x;
34743 	void *voidptr;
34744 
34745 	/* Caller has already eaten the first character ('(') which we don't need. */
34746 
34747 	p = js_ctx->p;
34748 
34749 	for (;;) {
34750 		x = *p;
34751 
34752 		/* Assume that the native representation never contains a closing
34753 		 * parenthesis.
34754 		 */
34755 
34756 		if (x == DUK_ASC_RPAREN) {
34757 			break;
34758 		} else if (x <= 0) {
34759 			/* NUL term or -1 (EOF), NUL check would suffice */
34760 			goto syntax_error;
34761 		}
34762 		p++;
34763 	}
34764 
34765 	/* There is no need to NUL delimit the sscanf() call: trailing garbage is
34766 	 * ignored and there is always a NUL terminator which will force an error
34767 	 * if no error is encountered before it.  It's possible that the scan
34768 	 * would scan further than between [js_ctx->p,p[ though and we'd advance
34769 	 * by less than the scanned value.
34770 	 *
34771 	 * Because pointers are platform specific, a failure to scan a pointer
34772 	 * results in a null pointer which is a better placeholder than a missing
34773 	 * value or an error.
34774 	 */
34775 
34776 	voidptr = NULL;
34777 	(void) DUK_SSCANF((const char *) js_ctx->p, DUK_STR_FMT_PTR, &voidptr);
34778 	duk_push_pointer(thr, voidptr);
34779 	js_ctx->p = p + 1;  /* skip ')' */
34780 
34781 	/* [ ... ptr ] */
34782 
34783 	return;
34784 
34785  syntax_error:
34786 	duk__dec_syntax_error(js_ctx);
34787 	DUK_UNREACHABLE();
34788 }
34789 #endif  /* DUK_USE_JX */
34790 
34791 #if defined(DUK_USE_JX)
duk__dec_buffer(duk_json_dec_ctx * js_ctx)34792 DUK_LOCAL void duk__dec_buffer(duk_json_dec_ctx *js_ctx) {
34793 	duk_hthread *thr = js_ctx->thr;
34794 	const duk_uint8_t *p;
34795 	duk_uint8_t *buf;
34796 	duk_size_t src_len;
34797 	duk_small_int_t x;
34798 
34799 	/* Caller has already eaten the first character ('|') which we don't need. */
34800 
34801 	p = js_ctx->p;
34802 
34803 	/* XXX: Would be nice to share the fast path loop from duk_hex_decode()
34804 	 * and avoid creating a temporary buffer.  However, there are some
34805 	 * differences which prevent trivial sharing:
34806 	 *
34807 	 *   - Pipe char detection
34808 	 *   - EOF detection
34809 	 *   - Unknown length of input and output
34810 	 *
34811 	 * The best approach here would be a bufwriter and a reasonaly sized
34812 	 * safe inner loop (e.g. 64 output bytes at a time).
34813 	 */
34814 
34815 	for (;;) {
34816 		x = *p;
34817 
34818 		/* This loop intentionally does not ensure characters are valid
34819 		 * ([0-9a-fA-F]) because the hex decode call below will do that.
34820 		 */
34821 		if (x == DUK_ASC_PIPE) {
34822 			break;
34823 		} else if (x <= 0) {
34824 			/* NUL term or -1 (EOF), NUL check would suffice */
34825 			goto syntax_error;
34826 		}
34827 		p++;
34828 	}
34829 
34830 	/* XXX: this is not very nice; unnecessary copy is made. */
34831 	src_len = (duk_size_t) (p - js_ctx->p);
34832 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, src_len);
34833 	DUK_ASSERT(buf != NULL);
34834 	duk_memcpy((void *) buf, (const void *) js_ctx->p, src_len);
34835 	duk_hex_decode(thr, -1);
34836 
34837 	js_ctx->p = p + 1;  /* skip '|' */
34838 
34839 	/* [ ... buf ] */
34840 
34841 	return;
34842 
34843  syntax_error:
34844 	duk__dec_syntax_error(js_ctx);
34845 	DUK_UNREACHABLE();
34846 }
34847 #endif  /* DUK_USE_JX */
34848 
34849 /* Parse a number, other than NaN or +/- Infinity */
duk__dec_number(duk_json_dec_ctx * js_ctx)34850 DUK_LOCAL void duk__dec_number(duk_json_dec_ctx *js_ctx) {
34851 	duk_hthread *thr = js_ctx->thr;
34852 	const duk_uint8_t *p_start;
34853 	const duk_uint8_t *p;
34854 	duk_uint8_t x;
34855 	duk_small_uint_t s2n_flags;
34856 
34857 	DUK_DDD(DUK_DDDPRINT("parse_number"));
34858 
34859 	p_start = js_ctx->p;
34860 
34861 	/* First pass parse is very lenient (e.g. allows '1.2.3') and extracts a
34862 	 * string for strict number parsing.
34863 	 */
34864 
34865 	p = js_ctx->p;
34866 	for (;;) {
34867 		x = *p;
34868 
34869 		DUK_DDD(DUK_DDDPRINT("parse_number: p_start=%p, p=%p, p_end=%p, x=%ld",
34870 		                     (const void *) p_start, (const void *) p,
34871 		                     (const void *) js_ctx->p_end, (long) x));
34872 
34873 #if defined(DUK_USE_JSON_DECNUMBER_FASTPATH)
34874 		/* This fast path is pretty marginal in practice.
34875 		 * XXX: candidate for removal.
34876 		 */
34877 		DUK_ASSERT(duk__json_decnumber_lookup[0x00] == 0x00);  /* end-of-input breaks */
34878 		if (duk__json_decnumber_lookup[x] == 0) {
34879 			break;
34880 		}
34881 #else  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34882 		if (!((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
34883 		      (x == DUK_ASC_PERIOD || x == DUK_ASC_LC_E ||
34884 		       x == DUK_ASC_UC_E || x == DUK_ASC_MINUS || x == DUK_ASC_PLUS))) {
34885 			/* Plus sign must be accepted for positive exponents
34886 			 * (e.g. '1.5e+2').  This clause catches NULs.
34887 			 */
34888 			break;
34889 		}
34890 #endif  /* DUK_USE_JSON_DECNUMBER_FASTPATH */
34891 		p++;  /* safe, because matched (NUL causes a break) */
34892 	}
34893 	js_ctx->p = p;
34894 
34895 	DUK_ASSERT(js_ctx->p > p_start);
34896 	duk_push_lstring(thr, (const char *) p_start, (duk_size_t) (p - p_start));
34897 
34898 	s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
34899 	            DUK_S2N_FLAG_ALLOW_MINUS |  /* but don't allow leading plus */
34900 	            DUK_S2N_FLAG_ALLOW_FRAC;
34901 
34902 	DUK_DDD(DUK_DDDPRINT("parse_number: string before parsing: %!T",
34903 	                     (duk_tval *) duk_get_tval(thr, -1)));
34904 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
34905 	if (duk_is_nan(thr, -1)) {
34906 		duk__dec_syntax_error(js_ctx);
34907 	}
34908 	DUK_ASSERT(duk_is_number(thr, -1));
34909 	DUK_DDD(DUK_DDDPRINT("parse_number: final number: %!T",
34910 	                     (duk_tval *) duk_get_tval(thr, -1)));
34911 
34912 	/* [ ... num ] */
34913 }
34914 
duk__dec_objarr_entry(duk_json_dec_ctx * js_ctx)34915 DUK_LOCAL void duk__dec_objarr_entry(duk_json_dec_ctx *js_ctx) {
34916 	duk_hthread *thr = js_ctx->thr;
34917 	duk_require_stack(thr, DUK_JSON_DEC_REQSTACK);
34918 
34919 	/* c recursion check */
34920 
34921 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
34922 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
34923 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
34924 		DUK_ERROR_RANGE(thr, DUK_STR_JSONDEC_RECLIMIT);
34925 		DUK_WO_NORETURN(return;);
34926 	}
34927 	js_ctx->recursion_depth++;
34928 }
34929 
duk__dec_objarr_exit(duk_json_dec_ctx * js_ctx)34930 DUK_LOCAL void duk__dec_objarr_exit(duk_json_dec_ctx *js_ctx) {
34931 	/* c recursion check */
34932 
34933 	DUK_ASSERT(js_ctx->recursion_depth > 0);
34934 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
34935 	js_ctx->recursion_depth--;
34936 }
34937 
duk__dec_object(duk_json_dec_ctx * js_ctx)34938 DUK_LOCAL void duk__dec_object(duk_json_dec_ctx *js_ctx) {
34939 	duk_hthread *thr = js_ctx->thr;
34940 	duk_int_t key_count;  /* XXX: a "first" flag would suffice */
34941 	duk_uint8_t x;
34942 
34943 	DUK_DDD(DUK_DDDPRINT("parse_object"));
34944 
34945 	duk__dec_objarr_entry(js_ctx);
34946 
34947 	duk_push_object(thr);
34948 
34949 	/* Initial '{' has been checked and eaten by caller. */
34950 
34951 	key_count = 0;
34952 	for (;;) {
34953 		x = duk__dec_get_nonwhite(js_ctx);
34954 
34955 		DUK_DDD(DUK_DDDPRINT("parse_object: obj=%!T, x=%ld, key_count=%ld",
34956 		                     (duk_tval *) duk_get_tval(thr, -1),
34957 		                     (long) x, (long) key_count));
34958 
34959 		/* handle comma and closing brace */
34960 
34961 		if (x == DUK_ASC_COMMA && key_count > 0) {
34962 			/* accept comma, expect new value */
34963 			x = duk__dec_get_nonwhite(js_ctx);
34964 		} else if (x == DUK_ASC_RCURLY) {
34965 			/* eat closing brace */
34966 			break;
34967 		} else if (key_count == 0) {
34968 			/* accept anything, expect first value (EOF will be
34969 			 * caught by key parsing below.
34970 			 */
34971 			;
34972 		} else {
34973 			/* catches EOF (NUL) and initial comma */
34974 			goto syntax_error;
34975 		}
34976 
34977 		/* parse key and value */
34978 
34979 		if (x == DUK_ASC_DOUBLEQUOTE) {
34980 			duk__dec_string(js_ctx);
34981 #if defined(DUK_USE_JX)
34982 		} else if (js_ctx->flag_ext_custom &&
34983 		           duk_unicode_is_identifier_start((duk_codepoint_t) x)) {
34984 			duk__dec_plain_string(js_ctx);
34985 #endif
34986 		} else {
34987 			goto syntax_error;
34988 		}
34989 
34990 		/* [ ... obj key ] */
34991 
34992 		x = duk__dec_get_nonwhite(js_ctx);
34993 		if (x != DUK_ASC_COLON) {
34994 			goto syntax_error;
34995 		}
34996 
34997 		duk__dec_value(js_ctx);
34998 
34999 		/* [ ... obj key val ] */
35000 
35001 		duk_xdef_prop_wec(thr, -3);
35002 
35003 		/* [ ... obj ] */
35004 
35005 		key_count++;
35006 	}
35007 
35008 	/* [ ... obj ] */
35009 
35010 	DUK_DDD(DUK_DDDPRINT("parse_object: final object is %!T",
35011 	                     (duk_tval *) duk_get_tval(thr, -1)));
35012 
35013 	duk__dec_objarr_exit(js_ctx);
35014 	return;
35015 
35016  syntax_error:
35017 	duk__dec_syntax_error(js_ctx);
35018 	DUK_UNREACHABLE();
35019 }
35020 
duk__dec_array(duk_json_dec_ctx * js_ctx)35021 DUK_LOCAL void duk__dec_array(duk_json_dec_ctx *js_ctx) {
35022 	duk_hthread *thr = js_ctx->thr;
35023 	duk_uarridx_t arr_idx;
35024 	duk_uint8_t x;
35025 
35026 	DUK_DDD(DUK_DDDPRINT("parse_array"));
35027 
35028 	duk__dec_objarr_entry(js_ctx);
35029 
35030 	duk_push_array(thr);
35031 
35032 	/* Initial '[' has been checked and eaten by caller. */
35033 
35034 	arr_idx = 0;
35035 	for (;;) {
35036 		x = duk__dec_get_nonwhite(js_ctx);
35037 
35038 		DUK_DDD(DUK_DDDPRINT("parse_array: arr=%!T, x=%ld, arr_idx=%ld",
35039 		                     (duk_tval *) duk_get_tval(thr, -1),
35040 		                     (long) x, (long) arr_idx));
35041 
35042 		/* handle comma and closing bracket */
35043 
35044 		if ((x == DUK_ASC_COMMA) && (arr_idx != 0)) {
35045 			/* accept comma, expect new value */
35046 			;
35047 		} else if (x == DUK_ASC_RBRACKET) {
35048 			/* eat closing bracket */
35049 			break;
35050 		} else if (arr_idx == 0) {
35051 			/* accept anything, expect first value (EOF will be
35052 			 * caught by duk__dec_value() below.
35053 			 */
35054 			js_ctx->p--;  /* backtrack (safe) */
35055 		} else {
35056 			/* catches EOF (NUL) and initial comma */
35057 			goto syntax_error;
35058 		}
35059 
35060 		/* parse value */
35061 
35062 		duk__dec_value(js_ctx);
35063 
35064 		/* [ ... arr val ] */
35065 
35066 		duk_xdef_prop_index_wec(thr, -2, arr_idx);
35067 		arr_idx++;
35068 	}
35069 
35070 	/* Must set 'length' explicitly when using duk_xdef_prop_xxx() to
35071 	 * set the values.
35072 	 */
35073 
35074 	duk_set_length(thr, -1, arr_idx);
35075 
35076 	/* [ ... arr ] */
35077 
35078 	DUK_DDD(DUK_DDDPRINT("parse_array: final array is %!T",
35079 	                     (duk_tval *) duk_get_tval(thr, -1)));
35080 
35081 	duk__dec_objarr_exit(js_ctx);
35082 	return;
35083 
35084  syntax_error:
35085 	duk__dec_syntax_error(js_ctx);
35086 	DUK_UNREACHABLE();
35087 }
35088 
duk__dec_value(duk_json_dec_ctx * js_ctx)35089 DUK_LOCAL void duk__dec_value(duk_json_dec_ctx *js_ctx) {
35090 	duk_hthread *thr = js_ctx->thr;
35091 	duk_uint8_t x;
35092 
35093 	x = duk__dec_get_nonwhite(js_ctx);
35094 
35095 	DUK_DDD(DUK_DDDPRINT("parse_value: initial x=%ld", (long) x));
35096 
35097 	/* Note: duk__dec_req_stridx() backtracks one char */
35098 
35099 	if (x == DUK_ASC_DOUBLEQUOTE) {
35100 		duk__dec_string(js_ctx);
35101 	} else if ((x >= DUK_ASC_0 && x <= DUK_ASC_9) || (x == DUK_ASC_MINUS)) {
35102 #if defined(DUK_USE_JX)
35103 		if (js_ctx->flag_ext_custom && x == DUK_ASC_MINUS && duk__dec_peek(js_ctx) == DUK_ASC_UC_I) {
35104 			duk__dec_req_stridx(js_ctx, DUK_STRIDX_MINUS_INFINITY);  /* "-Infinity", '-' has been eaten */
35105 			duk_push_number(thr, -DUK_DOUBLE_INFINITY);
35106 		} else {
35107 #else
35108 		{  /* unconditional block */
35109 #endif
35110 			/* We already ate 'x', so backup one byte. */
35111 			js_ctx->p--;  /* safe */
35112 			duk__dec_number(js_ctx);
35113 		}
35114 	} else if (x == DUK_ASC_LC_T) {
35115 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_TRUE);
35116 		duk_push_true(thr);
35117 	} else if (x == DUK_ASC_LC_F) {
35118 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_FALSE);
35119 		duk_push_false(thr);
35120 	} else if (x == DUK_ASC_LC_N) {
35121 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_NULL);
35122 		duk_push_null(thr);
35123 #if defined(DUK_USE_JX)
35124 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LC_U) {
35125 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_LC_UNDEFINED);
35126 		duk_push_undefined(thr);
35127 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_N) {
35128 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_NAN);
35129 		duk_push_nan(thr);
35130 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_UC_I) {
35131 		duk__dec_req_stridx(js_ctx, DUK_STRIDX_INFINITY);
35132 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
35133 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_LPAREN) {
35134 		duk__dec_pointer(js_ctx);
35135 	} else if (js_ctx->flag_ext_custom && x == DUK_ASC_PIPE) {
35136 		duk__dec_buffer(js_ctx);
35137 #endif
35138 	} else if (x == DUK_ASC_LCURLY) {
35139 		duk__dec_object(js_ctx);
35140 	} else if (x == DUK_ASC_LBRACKET) {
35141 		duk__dec_array(js_ctx);
35142 	} else {
35143 		/* catches EOF (NUL) */
35144 		goto syntax_error;
35145 	}
35146 
35147 	duk__dec_eat_white(js_ctx);
35148 
35149 	/* [ ... val ] */
35150 	return;
35151 
35152  syntax_error:
35153 	duk__dec_syntax_error(js_ctx);
35154 	DUK_UNREACHABLE();
35155 }
35156 
35157 /* Recursive value reviver, implements the Walk() algorithm.  No C recursion
35158  * check is done here because the initial parsing step will already ensure
35159  * there is a reasonable limit on C recursion depth and hence object depth.
35160  */
35161 DUK_LOCAL void duk__dec_reviver_walk(duk_json_dec_ctx *js_ctx) {
35162 	duk_hthread *thr = js_ctx->thr;
35163 	duk_hobject *h;
35164 	duk_uarridx_t i, arr_len;
35165 
35166 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, holder=%!T, name=%!T",
35167 	                     (long) duk_get_top(thr),
35168 	                     (duk_tval *) duk_get_tval(thr, -2),
35169 	                     (duk_tval *) duk_get_tval(thr, -1)));
35170 
35171 	duk_dup_top(thr);
35172 	duk_get_prop(thr, -3);  /* -> [ ... holder name val ] */
35173 
35174 	h = duk_get_hobject(thr, -1);
35175 	if (h != NULL) {
35176 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
35177 			arr_len = (duk_uarridx_t) duk_get_length(thr, -1);
35178 			for (i = 0; i < arr_len; i++) {
35179 				/* [ ... holder name val ] */
35180 
35181 				DUK_DDD(DUK_DDDPRINT("walk: array, top=%ld, i=%ld, arr_len=%ld, holder=%!T, name=%!T, val=%!T",
35182 				                     (long) duk_get_top(thr), (long) i, (long) arr_len,
35183 				                     (duk_tval *) duk_get_tval(thr, -3), (duk_tval *) duk_get_tval(thr, -2),
35184 				                     (duk_tval *) duk_get_tval(thr, -1)));
35185 
35186 				duk_dup_top(thr);
35187 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... holder name val val ToString(i) ] */
35188 				duk__dec_reviver_walk(js_ctx);  /* -> [ ... holder name val new_elem ] */
35189 
35190 				if (duk_is_undefined(thr, -1)) {
35191 					duk_pop(thr);
35192 					duk_del_prop_index(thr, -1, i);
35193 				} else {
35194 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35195 					 * here but it currently makes some assumptions that might
35196 					 * not hold (e.g. that previous property is not an accessor).
35197 					 */
35198 					duk_put_prop_index(thr, -2, i);
35199 				}
35200 			}
35201 		} else {
35202 			/* [ ... holder name val ] */
35203 			duk_enum(thr, -1, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);
35204 			while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
35205 				DUK_DDD(DUK_DDDPRINT("walk: object, top=%ld, holder=%!T, name=%!T, val=%!T, enum=%!iT, obj_key=%!T",
35206 				                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -5),
35207 				                     (duk_tval *) duk_get_tval(thr, -4), (duk_tval *) duk_get_tval(thr, -3),
35208 				                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
35209 
35210 				/* [ ... holder name val enum obj_key ] */
35211 				duk_dup_m3(thr);
35212 				duk_dup_m2(thr);
35213 
35214 				/* [ ... holder name val enum obj_key val obj_key ] */
35215 				duk__dec_reviver_walk(js_ctx);
35216 
35217 				/* [ ... holder name val enum obj_key new_elem ] */
35218 				if (duk_is_undefined(thr, -1)) {
35219 					duk_pop(thr);
35220 					duk_del_prop(thr, -3);
35221 				} else {
35222 					/* XXX: duk_xdef_prop_index_wec() would be more appropriate
35223 					 * here but it currently makes some assumptions that might
35224 					 * not hold (e.g. that previous property is not an accessor).
35225 					 *
35226 					 * Using duk_put_prop() works incorrectly with '__proto__'
35227 					 * if the own property with that name has been deleted.  This
35228 					 * does not happen normally, but a clever reviver can trigger
35229 					 * that, see complex reviver case in: test-bug-json-parse-__proto__.js.
35230 					 */
35231 					duk_put_prop(thr, -4);
35232 				}
35233 			}
35234 			duk_pop(thr);  /* pop enum */
35235 		}
35236 	}
35237 
35238 	/* [ ... holder name val ] */
35239 
35240 	duk_dup(thr, js_ctx->idx_reviver);
35241 	duk_insert(thr, -4);  /* -> [ ... reviver holder name val ] */
35242 	duk_call_method(thr, 2);  /* -> [ ... res ] */
35243 
35244 	DUK_DDD(DUK_DDDPRINT("walk: top=%ld, result=%!T",
35245 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, -1)));
35246 }
35247 
35248 /*
35249  *  Stringify implementation.
35250  */
35251 
35252 #define DUK__EMIT_1(js_ctx,ch)          duk__emit_1((js_ctx), (duk_uint_fast8_t) (ch))
35253 #define DUK__EMIT_2(js_ctx,ch1,ch2)     duk__emit_2((js_ctx), (duk_uint_fast8_t) (ch1), (duk_uint_fast8_t) (ch2))
35254 #define DUK__EMIT_HSTR(js_ctx,h)        duk__emit_hstring((js_ctx), (h))
35255 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35256 #define DUK__EMIT_CSTR(js_ctx,p)        duk__emit_cstring((js_ctx), (p))
35257 #endif
35258 #define DUK__EMIT_STRIDX(js_ctx,i)      duk__emit_stridx((js_ctx), (i))
35259 #define DUK__UNEMIT_1(js_ctx)           duk__unemit_1((js_ctx))
35260 
35261 DUK_LOCAL void duk__emit_1(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch) {
35262 	DUK_BW_WRITE_ENSURE_U8(js_ctx->thr, &js_ctx->bw, ch);
35263 }
35264 
35265 DUK_LOCAL void duk__emit_2(duk_json_enc_ctx *js_ctx, duk_uint_fast8_t ch1, duk_uint_fast8_t ch2) {
35266 	DUK_BW_WRITE_ENSURE_U8_2(js_ctx->thr, &js_ctx->bw, ch1, ch2);
35267 }
35268 
35269 DUK_LOCAL void duk__emit_hstring(duk_json_enc_ctx *js_ctx, duk_hstring *h) {
35270 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35271 }
35272 
35273 #if defined(DUK_USE_FASTINT) || defined(DUK_USE_JX) || defined(DUK_USE_JC)
35274 DUK_LOCAL void duk__emit_cstring(duk_json_enc_ctx *js_ctx, const char *str) {
35275 	DUK_BW_WRITE_ENSURE_CSTRING(js_ctx->thr, &js_ctx->bw, str);
35276 }
35277 #endif
35278 
35279 DUK_LOCAL void duk__emit_stridx(duk_json_enc_ctx *js_ctx, duk_small_uint_t stridx) {
35280 	duk_hstring *h;
35281 
35282 	DUK_ASSERT_STRIDX_VALID(stridx);
35283 	h = DUK_HTHREAD_GET_STRING(js_ctx->thr, stridx);
35284 	DUK_ASSERT(h != NULL);
35285 
35286 	DUK_BW_WRITE_ENSURE_HSTRING(js_ctx->thr, &js_ctx->bw, h);
35287 }
35288 
35289 DUK_LOCAL void duk__unemit_1(duk_json_enc_ctx *js_ctx) {
35290 	DUK_ASSERT(DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw) >= 1);
35291 	DUK_BW_ADD_PTR(js_ctx->thr, &js_ctx->bw, -1);
35292 }
35293 
35294 #define DUK__MKESC(nybbles,esc1,esc2)  \
35295 	(((duk_uint_fast32_t) (nybbles)) << 16) | \
35296 	(((duk_uint_fast32_t) (esc1)) << 8) | \
35297 	((duk_uint_fast32_t) (esc2))
35298 
35299 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) {
35300 	duk_uint_fast32_t tmp;
35301 	duk_small_uint_t dig;
35302 
35303 	DUK_UNREF(js_ctx);
35304 
35305 	/* Caller ensures space for at least DUK__JSON_MAX_ESC_LEN. */
35306 
35307 	/* Select appropriate escape format automatically, and set 'tmp' to a
35308 	 * value encoding both the escape format character and the nybble count:
35309 	 *
35310 	 *   (nybble_count << 16) | (escape_char1) | (escape_char2)
35311 	 */
35312 
35313 #if defined(DUK_USE_JX)
35314 	if (DUK_LIKELY(cp < 0x100UL)) {
35315 		if (DUK_UNLIKELY(js_ctx->flag_ext_custom != 0U)) {
35316 			tmp = DUK__MKESC(2, DUK_ASC_BACKSLASH, DUK_ASC_LC_X);
35317 		} else {
35318 			tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35319 		}
35320 	} else
35321 #endif
35322 	if (DUK_LIKELY(cp < 0x10000UL)) {
35323 		tmp = DUK__MKESC(4, DUK_ASC_BACKSLASH, DUK_ASC_LC_U);
35324 	} else {
35325 #if defined(DUK_USE_JX)
35326 		if (DUK_LIKELY(js_ctx->flag_ext_custom != 0U)) {
35327 			tmp = DUK__MKESC(8, DUK_ASC_BACKSLASH, DUK_ASC_UC_U);
35328 		} else
35329 #endif
35330 		{
35331 			/* In compatible mode and standard JSON mode, output
35332 			 * something useful for non-BMP characters.  This won't
35333 			 * roundtrip but will still be more or less readable and
35334 			 * more useful than an error.
35335 			 */
35336 			tmp = DUK__MKESC(8, DUK_ASC_UC_U, DUK_ASC_PLUS);
35337 		}
35338 	}
35339 
35340 	*q++ = (duk_uint8_t) ((tmp >> 8) & 0xff);
35341 	*q++ = (duk_uint8_t) (tmp & 0xff);
35342 
35343 	tmp = tmp >> 16;
35344 	while (tmp > 0) {
35345 		tmp--;
35346 		dig = (duk_small_uint_t) ((cp >> (4 * tmp)) & 0x0f);
35347 		*q++ = duk_lc_digits[dig];
35348 	}
35349 
35350 	return q;
35351 }
35352 
35353 DUK_LOCAL void duk__enc_key_autoquote(duk_json_enc_ctx *js_ctx, duk_hstring *k) {
35354 	const duk_int8_t *p, *p_start, *p_end;  /* Note: intentionally signed. */
35355 	duk_size_t k_len;
35356 	duk_codepoint_t cp;
35357 
35358 	DUK_ASSERT(k != NULL);
35359 
35360 	/* Accept ASCII strings which conform to identifier requirements
35361 	 * as being emitted without key quotes.  Since we only accept ASCII
35362 	 * there's no need for actual decoding: 'p' is intentionally signed
35363 	 * so that bytes >= 0x80 extend to negative values and are rejected
35364 	 * as invalid identifier codepoints.
35365 	 */
35366 
35367 	if (js_ctx->flag_avoid_key_quotes) {
35368 		k_len = DUK_HSTRING_GET_BYTELEN(k);
35369 		p_start = (const duk_int8_t *) DUK_HSTRING_GET_DATA(k);
35370 		p_end = p_start + k_len;
35371 		p = p_start;
35372 
35373 		if (p == p_end) {
35374 			/* Zero length string is not accepted without quotes */
35375 			goto quote_normally;
35376 		}
35377 		cp = (duk_codepoint_t) (*p++);
35378 		if (DUK_UNLIKELY(!duk_unicode_is_identifier_start(cp))) {
35379 			goto quote_normally;
35380 		}
35381 		while (p < p_end) {
35382 			cp = (duk_codepoint_t) (*p++);
35383 			if (DUK_UNLIKELY(!duk_unicode_is_identifier_part(cp))) {
35384 				goto quote_normally;
35385 			}
35386 		}
35387 
35388 		/* This seems faster than emitting bytes one at a time and
35389 		 * then potentially rewinding.
35390 		 */
35391 		DUK__EMIT_HSTR(js_ctx, k);
35392 		return;
35393 	}
35394 
35395  quote_normally:
35396 	duk__enc_quote_string(js_ctx, k);
35397 }
35398 
35399 /* The Quote(value) operation: quote a string.
35400  *
35401  * Stack policy: [ ] -> [ ].
35402  */
35403 
35404 DUK_LOCAL void duk__enc_quote_string(duk_json_enc_ctx *js_ctx, duk_hstring *h_str) {
35405 	duk_hthread *thr = js_ctx->thr;
35406 	const duk_uint8_t *p, *p_start, *p_end, *p_now, *p_tmp;
35407 	duk_uint8_t *q;
35408 	duk_ucodepoint_t cp;  /* typed for duk_unicode_decode_xutf8() */
35409 
35410 	DUK_DDD(DUK_DDDPRINT("duk__enc_quote_string: h_str=%!O", (duk_heaphdr *) h_str));
35411 
35412 	DUK_ASSERT(h_str != NULL);
35413 	p_start = DUK_HSTRING_GET_DATA(h_str);
35414 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_str);
35415 	p = p_start;
35416 
35417 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35418 
35419 	/* Encode string in small chunks, estimating the maximum expansion so that
35420 	 * there's no need to ensure space while processing the chunk.
35421 	 */
35422 
35423 	while (p < p_end) {
35424 		duk_size_t left, now, space;
35425 
35426 		left = (duk_size_t) (p_end - p);
35427 		now = (left > DUK__JSON_ENCSTR_CHUNKSIZE ?
35428 		       DUK__JSON_ENCSTR_CHUNKSIZE : left);
35429 
35430 		/* Maximum expansion per input byte is 6:
35431 		 *   - invalid UTF-8 byte causes "\uXXXX" to be emitted (6/1 = 6).
35432 		 *   - 2-byte UTF-8 encodes as "\uXXXX" (6/2 = 3).
35433 		 *   - 4-byte UTF-8 encodes as "\Uxxxxxxxx" (10/4 = 2.5).
35434 		 */
35435 		space = now * 6;
35436 		q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35437 
35438 		p_now = p + now;
35439 
35440 		while (p < p_now) {
35441 #if defined(DUK_USE_JSON_QUOTESTRING_FASTPATH)
35442 			duk_uint8_t b;
35443 
35444 			b = duk__json_quotestr_lookup[*p++];
35445 			if (DUK_LIKELY(b < 0x80)) {
35446 				/* Most input bytes go through here. */
35447 				*q++ = b;
35448 			} else if (b >= 0xa0) {
35449 				*q++ = DUK_ASC_BACKSLASH;
35450 				*q++ = (duk_uint8_t) (b - 0x80);
35451 			} else if (b == 0x80) {
35452 				cp = (duk_ucodepoint_t) (*(p - 1));
35453 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35454 			} else if (b == 0x7f && js_ctx->flag_ascii_only) {
35455 				/* 0x7F is special */
35456 				DUK_ASSERT(b == 0x81);
35457 				cp = (duk_ucodepoint_t) 0x7f;
35458 				q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35459 			} else {
35460 				DUK_ASSERT(b == 0x81);
35461 				p--;
35462 
35463 				/* slow path is shared */
35464 #else  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35465 			cp = *p;
35466 
35467 			if (DUK_LIKELY(cp <= 0x7f)) {
35468 				/* ascii fast path: avoid decoding utf-8 */
35469 				p++;
35470 				if (cp == 0x22 || cp == 0x5c) {
35471 					/* double quote or backslash */
35472 					*q++ = DUK_ASC_BACKSLASH;
35473 					*q++ = (duk_uint8_t) cp;
35474 				} else if (cp < 0x20) {
35475 					duk_uint_fast8_t esc_char;
35476 
35477 					/* This approach is a bit shorter than a straight
35478 					 * if-else-ladder and also a bit faster.
35479 					 */
35480 					if (cp < (sizeof(duk__json_quotestr_esc) / sizeof(duk_uint8_t)) &&
35481 					    (esc_char = duk__json_quotestr_esc[cp]) != 0) {
35482 						*q++ = DUK_ASC_BACKSLASH;
35483 						*q++ = (duk_uint8_t) esc_char;
35484 					} else {
35485 						q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35486 					}
35487 				} else if (cp == 0x7f && js_ctx->flag_ascii_only) {
35488 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35489 				} else {
35490 					/* any other printable -> as is */
35491 					*q++ = (duk_uint8_t) cp;
35492 				}
35493 			} else {
35494 				/* slow path is shared */
35495 #endif  /* DUK_USE_JSON_QUOTESTRING_FASTPATH */
35496 
35497 				/* slow path decode */
35498 
35499 				/* If XUTF-8 decoding fails, treat the offending byte as a codepoint directly
35500 				 * and go forward one byte.  This is of course very lossy, but allows some kind
35501 				 * of output to be produced even for internal strings which don't conform to
35502 				 * XUTF-8.  All standard ECMAScript strings are always CESU-8, so this behavior
35503 				 * does not violate the ECMAScript specification.  The behavior is applied to
35504 				 * all modes, including ECMAScript standard JSON.  Because the current XUTF-8
35505 				 * decoding is not very strict, this behavior only really affects initial bytes
35506 				 * and truncated codepoints.
35507 				 *
35508 				 * Another alternative would be to scan forwards to start of next codepoint
35509 				 * (or end of input) and emit just one replacement codepoint.
35510 				 */
35511 
35512 				p_tmp = p;
35513 				if (!duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp)) {
35514 					/* Decode failed. */
35515 					cp = *p_tmp;
35516 					p = p_tmp + 1;
35517 				}
35518 
35519 #if defined(DUK_USE_NONSTD_JSON_ESC_U2028_U2029)
35520 				if (js_ctx->flag_ascii_only || cp == 0x2028 || cp == 0x2029) {
35521 #else
35522 				if (js_ctx->flag_ascii_only) {
35523 #endif
35524 					q = duk__emit_esc_auto_fast(js_ctx, cp, q);
35525 				} else {
35526 					/* as is */
35527 					DUK_RAW_WRITE_XUTF8(q, cp);
35528 				}
35529 			}
35530 		}
35531 
35532 		DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35533 	}
35534 
35535 	DUK__EMIT_1(js_ctx, DUK_ASC_DOUBLEQUOTE);
35536 }
35537 
35538 /* Encode a double (checked by caller) from stack top.  Stack top may be
35539  * replaced by serialized string but is not popped (caller does that).
35540  */
35541 DUK_LOCAL void duk__enc_double(duk_json_enc_ctx *js_ctx) {
35542 	duk_hthread *thr;
35543 	duk_tval *tv;
35544 	duk_double_t d;
35545 	duk_small_int_t c;
35546 	duk_small_int_t s;
35547 	duk_small_uint_t stridx;
35548 	duk_small_uint_t n2s_flags;
35549 	duk_hstring *h_str;
35550 
35551 	DUK_ASSERT(js_ctx != NULL);
35552 	thr = js_ctx->thr;
35553 	DUK_ASSERT(thr != NULL);
35554 
35555 	/* Caller must ensure 'tv' is indeed a double and not a fastint! */
35556 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
35557 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
35558 	d = DUK_TVAL_GET_DOUBLE(tv);
35559 
35560 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
35561 	s = (duk_small_int_t) DUK_SIGNBIT(d);
35562 	DUK_UNREF(s);
35563 
35564 	if (DUK_LIKELY(!(c == DUK_FP_INFINITE || c == DUK_FP_NAN))) {
35565 		DUK_ASSERT(DUK_ISFINITE(d));
35566 
35567 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35568 		/* Negative zero needs special handling in JX/JC because
35569 		 * it would otherwise serialize to '0', not '-0'.
35570 		 */
35571 		if (DUK_UNLIKELY(c == DUK_FP_ZERO && s != 0 &&
35572 		                 (js_ctx->flag_ext_custom_or_compatible))) {
35573 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_ZERO);  /* '-0' */
35574 		} else
35575 #endif  /* DUK_USE_JX || DUK_USE_JC */
35576 		{
35577 			n2s_flags = 0;
35578 			/* [ ... number ] -> [ ... string ] */
35579 			duk_numconv_stringify(thr, 10 /*radix*/, 0 /*digits*/, n2s_flags);
35580 		}
35581 		h_str = duk_known_hstring(thr, -1);
35582 		DUK__EMIT_HSTR(js_ctx, h_str);
35583 		return;
35584 	}
35585 
35586 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35587 	if (!(js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
35588 	                       DUK_JSON_FLAG_EXT_COMPATIBLE))) {
35589 		stridx = DUK_STRIDX_LC_NULL;
35590 	} else if (c == DUK_FP_NAN) {
35591 		stridx = js_ctx->stridx_custom_nan;
35592 	} else if (s == 0) {
35593 		stridx = js_ctx->stridx_custom_posinf;
35594 	} else {
35595 		stridx = js_ctx->stridx_custom_neginf;
35596 	}
35597 #else
35598 	stridx = DUK_STRIDX_LC_NULL;
35599 #endif
35600 	DUK__EMIT_STRIDX(js_ctx, stridx);
35601 }
35602 
35603 #if defined(DUK_USE_FASTINT)
35604 /* Encode a fastint from duk_tval ptr, no value stack effects. */
35605 DUK_LOCAL void duk__enc_fastint_tval(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
35606 	duk_int64_t v;
35607 
35608 	/* Fastint range is signed 48-bit so longest value is -2^47 = -140737488355328
35609 	 * (16 chars long), longest signed 64-bit value is -2^63 = -9223372036854775808
35610 	 * (20 chars long).  Alloc space for 64-bit range to be safe.
35611 	 */
35612 	duk_uint8_t buf[20 + 1];
35613 
35614 	/* Caller must ensure 'tv' is indeed a fastint! */
35615 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
35616 	v = DUK_TVAL_GET_FASTINT(tv);
35617 
35618 	/* XXX: There are no format strings in duk_config.h yet, could add
35619 	 * one for formatting duk_int64_t.  For now, assumes "%lld" and that
35620 	 * "long long" type exists.  Could also rely on C99 directly but that
35621 	 * won't work for older MSVC.
35622 	 */
35623 	DUK_SPRINTF((char *) buf, "%lld", (long long) v);
35624 	DUK__EMIT_CSTR(js_ctx, (const char *) buf);
35625 }
35626 #endif
35627 
35628 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35629 #if defined(DUK_USE_HEX_FASTPATH)
35630 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35631 	duk_uint8_t *q;
35632 	duk_uint16_t *q16;
35633 	duk_small_uint_t x;
35634 	duk_size_t i, len_safe;
35635 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35636 	duk_bool_t shift_dst;
35637 #endif
35638 
35639 	/* Unlike in duk_hex_encode() 'dst' is not necessarily aligned by 2.
35640 	 * For platforms where unaligned accesses are not allowed, shift 'dst'
35641 	 * ahead by 1 byte to get alignment and then duk_memmove() the result
35642 	 * in place.  The faster encoding loop makes up the difference.
35643 	 * There's always space for one extra byte because a terminator always
35644 	 * follows the hex data and that's been accounted for by the caller.
35645 	 */
35646 
35647 #if defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35648 	q16 = (duk_uint16_t *) (void *) dst;
35649 #else
35650 	shift_dst = (duk_bool_t) (((duk_size_t) dst) & 0x01U);
35651 	if (shift_dst) {
35652 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst not aligned -> step to dst + 1"));
35653 		q16 = (duk_uint16_t *) (void *) (dst + 1);
35654 	} else {
35655 		DUK_DD(DUK_DDPRINT("unaligned accesses not possible, dst is aligned"));
35656 		q16 = (duk_uint16_t *) (void *) dst;
35657 	}
35658 	DUK_ASSERT((((duk_size_t) q16) & 0x01U) == 0);
35659 #endif
35660 
35661 	len_safe = src_len & ~0x03U;
35662 	for (i = 0; i < len_safe; i += 4) {
35663 		q16[0] = duk_hex_enctab[src[i]];
35664 		q16[1] = duk_hex_enctab[src[i + 1]];
35665 		q16[2] = duk_hex_enctab[src[i + 2]];
35666 		q16[3] = duk_hex_enctab[src[i + 3]];
35667 		q16 += 4;
35668 	}
35669 	q = (duk_uint8_t *) q16;
35670 
35671 #if !defined(DUK_USE_UNALIGNED_ACCESSES_POSSIBLE)
35672 	if (shift_dst) {
35673 		q--;
35674 		duk_memmove((void *) dst, (const void *) (dst + 1), 2 * len_safe);
35675 		DUK_ASSERT(dst + 2 * len_safe == q);
35676 	}
35677 #endif
35678 
35679 	for (; i < src_len; i++) {
35680 		x = src[i];
35681 		*q++ = duk_lc_digits[x >> 4];
35682 		*q++ = duk_lc_digits[x & 0x0f];
35683 	}
35684 
35685 	return q;
35686 }
35687 #else  /* DUK_USE_HEX_FASTPATH */
35688 DUK_LOCAL duk_uint8_t *duk__enc_buffer_data_hex(const duk_uint8_t *src, duk_size_t src_len, duk_uint8_t *dst) {
35689 	const duk_uint8_t *p;
35690 	const duk_uint8_t *p_end;
35691 	duk_uint8_t *q;
35692 	duk_small_uint_t x;
35693 
35694 	p = src;
35695 	p_end = src + src_len;
35696 	q = dst;
35697 	while (p != p_end) {
35698 		x = *p++;
35699 		*q++ = duk_lc_digits[x >> 4];
35700 		*q++ = duk_lc_digits[x & 0x0f];
35701 	}
35702 
35703 	return q;
35704 }
35705 #endif  /* DUK_USE_HEX_FASTPATH */
35706 
35707 DUK_LOCAL void duk__enc_buffer_data(duk_json_enc_ctx *js_ctx, duk_uint8_t *buf_data, duk_size_t buf_len) {
35708 	duk_hthread *thr;
35709 	duk_uint8_t *q;
35710 	duk_size_t space;
35711 
35712 	thr = js_ctx->thr;
35713 
35714 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35715 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35716 
35717 	/* Buffer values are encoded in (lowercase) hex to make the
35718 	 * binary data readable.  Base64 or similar would be more
35719 	 * compact but less readable, and the point of JX/JC
35720 	 * variants is to be as useful to a programmer as possible.
35721 	 */
35722 
35723 	/* The #if defined() clutter here needs to handle the three
35724 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35725 	 */
35726 
35727 	/* Note: space must cater for both JX and JC. */
35728 	space = 9 + buf_len * 2 + 2;
35729 	DUK_ASSERT(DUK_HBUFFER_MAX_BYTELEN <= 0x7ffffffeUL);
35730 	DUK_ASSERT((space - 2) / 2 >= buf_len);  /* overflow not possible, buffer limits */
35731 	q = DUK_BW_ENSURE_GETPTR(thr, &js_ctx->bw, space);
35732 
35733 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35734 	if (js_ctx->flag_ext_custom)
35735 #endif
35736 #if defined(DUK_USE_JX)
35737 	{
35738 		*q++ = DUK_ASC_PIPE;
35739 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35740 		*q++ = DUK_ASC_PIPE;
35741 
35742 	}
35743 #endif
35744 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35745 	else
35746 #endif
35747 #if defined(DUK_USE_JC)
35748 	{
35749 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35750 		duk_memcpy((void *) q, (const void *) "{\"_buf\":\"", 9);  /* len: 9 */
35751 		q += 9;
35752 		q = duk__enc_buffer_data_hex(buf_data, buf_len, q);
35753 		*q++ = DUK_ASC_DOUBLEQUOTE;
35754 		*q++ = DUK_ASC_RCURLY;
35755 	}
35756 #endif
35757 
35758 	DUK_BW_SET_PTR(thr, &js_ctx->bw, q);
35759 }
35760 
35761 DUK_LOCAL void duk__enc_buffer_jx_jc(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35762 	duk__enc_buffer_data(js_ctx,
35763 	                     (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h),
35764 	                     (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
35765 }
35766 #endif  /* DUK_USE_JX || DUK_USE_JC */
35767 
35768 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
35769 DUK_LOCAL void duk__enc_buffer_json_fastpath(duk_json_enc_ctx *js_ctx, duk_hbuffer *h) {
35770 	duk_size_t i, n;
35771 	const duk_uint8_t *buf;
35772 	duk_uint8_t *q;
35773 
35774 	n = DUK_HBUFFER_GET_SIZE(h);
35775 	if (n == 0) {
35776 		DUK__EMIT_2(js_ctx, DUK_ASC_LCURLY, DUK_ASC_RCURLY);
35777 		return;
35778 	}
35779 
35780 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
35781 
35782 	/* Maximum encoded length with 32-bit index: 1 + 10 + 2 + 3 + 1 + 1 = 18,
35783 	 * with 64-bit index: 1 + 20 + 2 + 3 + 1 + 1 = 28.  32 has some slack.
35784 	 *
35785 	 * Note that because the output buffer is reallocated from time to time,
35786 	 * side effects (such as finalizers) affecting the buffer 'h' must be
35787 	 * disabled.  This is the case in the JSON.stringify() fast path.
35788 	 */
35789 
35790 	buf = (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(js_ctx->thr->heap, h);
35791 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35792 		for (i = 0; i < n; i++) {
35793 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth + 1);
35794 			q = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, 32);
35795 			q += DUK_SPRINTF((char *) q, "\"%lu\": %u,", (unsigned long) i, (unsigned int) buf[i]);
35796 			DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35797 		}
35798 	} else {
35799 		q = DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw);
35800 		for (i = 0; i < n; i++) {
35801 			q = DUK_BW_ENSURE_RAW(js_ctx->thr, &js_ctx->bw, 32, q);
35802 			q += DUK_SPRINTF((char *) q, "\"%lu\":%u,", (unsigned long) i, (unsigned int) buf[i]);
35803 		}
35804 		DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, q);
35805 	}
35806 	DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
35807 
35808 	if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
35809 		duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
35810 	}
35811 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
35812 }
35813 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
35814 
35815 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35816 DUK_LOCAL void duk__enc_pointer(duk_json_enc_ctx *js_ctx, void *ptr) {
35817 	char buf[64];  /* XXX: how to figure correct size? */
35818 	const char *fmt;
35819 
35820 	DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);  /* caller checks */
35821 	DUK_ASSERT(js_ctx->flag_ext_custom_or_compatible);
35822 
35823 	duk_memzero(buf, sizeof(buf));
35824 
35825 	/* The #if defined() clutter here needs to handle the three
35826 	 * cases: (1) JX+JC, (2) JX only, (3) JC only.
35827 	 */
35828 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35829 	if (js_ctx->flag_ext_custom)
35830 #endif
35831 #if defined(DUK_USE_JX)
35832 	{
35833 		fmt = ptr ? "(%p)" : "(null)";
35834 	}
35835 #endif
35836 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
35837 	else
35838 #endif
35839 #if defined(DUK_USE_JC)
35840 	{
35841 		DUK_ASSERT(js_ctx->flag_ext_compatible);
35842 		fmt = ptr ? "{\"_ptr\":\"%p\"}" : "{\"_ptr\":\"null\"}";
35843 	}
35844 #endif
35845 
35846 	/* When ptr == NULL, the format argument is unused. */
35847 	DUK_SNPRINTF(buf, sizeof(buf) - 1, fmt, ptr);  /* must not truncate */
35848 	DUK__EMIT_CSTR(js_ctx, buf);
35849 }
35850 #endif  /* DUK_USE_JX || DUK_USE_JC */
35851 
35852 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
35853 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
35854 DUK_LOCAL void duk__enc_bufobj(duk_json_enc_ctx *js_ctx, duk_hbufobj *h_bufobj) {
35855 	DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
35856 
35857 	if (h_bufobj->buf == NULL || !DUK_HBUFOBJ_VALID_SLICE(h_bufobj)) {
35858 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
35859 	} else {
35860 		/* Handle both full and partial slice (as long as covered). */
35861 		duk__enc_buffer_data(js_ctx,
35862 		                     (duk_uint8_t *) DUK_HBUFOBJ_GET_SLICE_BASE(js_ctx->thr->heap, h_bufobj),
35863 		                     (duk_size_t) h_bufobj->length);
35864 	}
35865 }
35866 #endif  /* DUK_USE_JX || DUK_USE_JC */
35867 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
35868 
35869 /* Indent helper.  Calling code relies on js_ctx->recursion_depth also being
35870  * directly related to indent depth.
35871  */
35872 #if defined(DUK_USE_PREFER_SIZE)
35873 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
35874 	DUK_ASSERT(js_ctx->h_gap != NULL);
35875 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
35876 
35877 	DUK__EMIT_1(js_ctx, 0x0a);
35878 	while (depth-- > 0) {
35879 		DUK__EMIT_HSTR(js_ctx, js_ctx->h_gap);
35880 	}
35881 }
35882 #else  /* DUK_USE_PREFER_SIZE */
35883 DUK_LOCAL void duk__enc_newline_indent(duk_json_enc_ctx *js_ctx, duk_uint_t depth) {
35884 	const duk_uint8_t *gap_data;
35885 	duk_size_t gap_len;
35886 	duk_size_t avail_bytes;   /* bytes of indent available for copying */
35887 	duk_size_t need_bytes;    /* bytes of indent still needed */
35888 	duk_uint8_t *p_start;
35889 	duk_uint8_t *p;
35890 
35891 	DUK_ASSERT(js_ctx->h_gap != NULL);
35892 	DUK_ASSERT(DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) > 0);  /* caller guarantees */
35893 
35894 	DUK__EMIT_1(js_ctx, 0x0a);
35895 	if (DUK_UNLIKELY(depth == 0)) {
35896 		return;
35897 	}
35898 
35899 	/* To handle deeper indents efficiently, make use of copies we've
35900 	 * already emitted.  In effect we can emit a sequence of 1, 2, 4,
35901 	 * 8, etc copies, and then finish the last run.  Byte counters
35902 	 * avoid multiply with gap_len on every loop.
35903 	 */
35904 
35905 	gap_data = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(js_ctx->h_gap);
35906 	gap_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap);
35907 	DUK_ASSERT(gap_len > 0);
35908 
35909 	need_bytes = gap_len * depth;
35910 	p = DUK_BW_ENSURE_GETPTR(js_ctx->thr, &js_ctx->bw, need_bytes);
35911 	p_start = p;
35912 
35913 	duk_memcpy((void *) p, (const void *) gap_data, (size_t) gap_len);
35914 	p += gap_len;
35915 	avail_bytes = gap_len;
35916 	DUK_ASSERT(need_bytes >= gap_len);
35917 	need_bytes -= gap_len;
35918 
35919 	while (need_bytes >= avail_bytes) {
35920 		duk_memcpy((void *) p, (const void *) p_start, (size_t) avail_bytes);
35921 		p += avail_bytes;
35922 		need_bytes -= avail_bytes;
35923 		avail_bytes <<= 1;
35924 	}
35925 
35926 	DUK_ASSERT(need_bytes < avail_bytes);  /* need_bytes may be zero */
35927 	duk_memcpy((void *) p, (const void *) p_start, (size_t) need_bytes);
35928 	p += need_bytes;
35929 	/*avail_bytes += need_bytes*/
35930 
35931 	DUK_BW_SET_PTR(js_ctx->thr, &js_ctx->bw, p);
35932 }
35933 #endif  /* DUK_USE_PREFER_SIZE */
35934 
35935 /* Shared entry handling for object/array serialization. */
35936 DUK_LOCAL void duk__enc_objarr_entry(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
35937 	duk_hthread *thr = js_ctx->thr;
35938 	duk_hobject *h_target;
35939 	duk_uint_fast32_t i, n;
35940 
35941 	*entry_top = duk_get_top(thr);
35942 
35943 	duk_require_stack(thr, DUK_JSON_ENC_REQSTACK);
35944 
35945 	/* Loop check using a hybrid approach: a fixed-size visited[] array
35946 	 * with overflow in a loop check object.
35947 	 */
35948 
35949 	h_target = duk_known_hobject(thr, -1);  /* object or array */
35950 
35951 	n = js_ctx->recursion_depth;
35952 	if (DUK_UNLIKELY(n > DUK_JSON_ENC_LOOPARRAY)) {
35953 		n = DUK_JSON_ENC_LOOPARRAY;
35954 	}
35955 	for (i = 0; i < n; i++) {
35956 		if (DUK_UNLIKELY(js_ctx->visiting[i] == h_target)) {
35957 			DUK_DD(DUK_DDPRINT("slow path loop detect"));
35958 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
35959 			DUK_WO_NORETURN(return;);
35960 		}
35961 	}
35962 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
35963 		js_ctx->visiting[js_ctx->recursion_depth] = h_target;
35964 	} else {
35965 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
35966 		duk_dup_top(thr);  /* -> [ ... voidp voidp ] */
35967 		if (duk_has_prop(thr, js_ctx->idx_loop)) {
35968 			DUK_ERROR_TYPE(thr, DUK_STR_CYCLIC_INPUT);
35969 			DUK_WO_NORETURN(return;);
35970 		}
35971 		duk_push_true(thr);  /* -> [ ... voidp true ] */
35972 		duk_put_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
35973 	}
35974 
35975 	/* C recursion check. */
35976 
35977 	DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
35978 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
35979 	if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
35980 		DUK_ERROR_RANGE(thr, DUK_STR_JSONENC_RECLIMIT);
35981 		DUK_WO_NORETURN(return;);
35982 	}
35983 	js_ctx->recursion_depth++;
35984 
35985 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
35986 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
35987 }
35988 
35989 /* Shared exit handling for object/array serialization. */
35990 DUK_LOCAL void duk__enc_objarr_exit(duk_json_enc_ctx *js_ctx, duk_idx_t *entry_top) {
35991 	duk_hthread *thr = js_ctx->thr;
35992 	duk_hobject *h_target;
35993 
35994 	/* C recursion check. */
35995 
35996 	DUK_ASSERT(js_ctx->recursion_depth > 0);
35997 	DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
35998 	js_ctx->recursion_depth--;
35999 
36000 	/* Loop check. */
36001 
36002 	h_target = duk_known_hobject(thr, *entry_top - 1);  /* original target at entry_top - 1 */
36003 
36004 	if (js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY) {
36005 		/* Previous entry was inside visited[], nothing to do. */
36006 	} else {
36007 		duk_push_sprintf(thr, DUK_STR_FMT_PTR, (void *) h_target);
36008 		duk_del_prop(thr, js_ctx->idx_loop);  /* -> [ ... ] */
36009 	}
36010 
36011 	/* Restore stack top after unbalanced code paths. */
36012 	duk_set_top(thr, *entry_top);
36013 
36014 	DUK_DDD(DUK_DDDPRINT("shared entry finished: top=%ld, loop=%!T",
36015 	                     (long) duk_get_top(thr), (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop)));
36016 }
36017 
36018 /* The JO(value) operation: encode object.
36019  *
36020  * Stack policy: [ object ] -> [ object ].
36021  */
36022 DUK_LOCAL void duk__enc_object(duk_json_enc_ctx *js_ctx) {
36023 	duk_hthread *thr = js_ctx->thr;
36024 	duk_hstring *h_key;
36025 	duk_idx_t entry_top;
36026 	duk_idx_t idx_obj;
36027 	duk_idx_t idx_keys;
36028 	duk_bool_t emitted;
36029 	duk_uarridx_t arr_len, i;
36030 	duk_size_t prev_size;
36031 
36032 	DUK_DDD(DUK_DDDPRINT("duk__enc_object: obj=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36033 
36034 	duk__enc_objarr_entry(js_ctx, &entry_top);
36035 
36036 	idx_obj = entry_top - 1;
36037 
36038 	if (js_ctx->idx_proplist >= 0) {
36039 		idx_keys = js_ctx->idx_proplist;
36040 	} else {
36041 		/* XXX: would be nice to enumerate an object at specified index */
36042 		duk_dup(thr, idx_obj);
36043 		(void) duk_hobject_get_enumerated_keys(thr, DUK_ENUM_OWN_PROPERTIES_ONLY /*flags*/);  /* [ ... target ] -> [ ... target keys ] */
36044 		idx_keys = duk_require_normalize_index(thr, -1);
36045 		/* leave stack unbalanced on purpose */
36046 	}
36047 
36048 	DUK_DDD(DUK_DDDPRINT("idx_keys=%ld, h_keys=%!T",
36049 	                     (long) idx_keys, (duk_tval *) duk_get_tval(thr, idx_keys)));
36050 
36051 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36052 
36053 	DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36054 
36055 	/* XXX: keys is an internal object with all keys to be processed
36056 	 * in its (gapless) array part.  Because nobody can touch the keys
36057 	 * object, we could iterate its array part directly (keeping in mind
36058 	 * that it can be reallocated).
36059 	 */
36060 
36061 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_keys);
36062 	emitted = 0;
36063 	for (i = 0; i < arr_len; i++) {
36064 		duk_get_prop_index(thr, idx_keys, i);  /* -> [ ... key ] */
36065 
36066 		DUK_DDD(DUK_DDDPRINT("object property loop: holder=%!T, key=%!T",
36067 		                     (duk_tval *) duk_get_tval(thr, idx_obj),
36068 		                     (duk_tval *) duk_get_tval(thr, -1)));
36069 
36070 		h_key = duk_known_hstring(thr, -1);
36071 		DUK_ASSERT(h_key != NULL);
36072 		DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(h_key));  /* proplist filtering; enum options */
36073 
36074 		prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36075 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36076 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36077 			duk__enc_key_autoquote(js_ctx, h_key);
36078 			DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36079 		} else {
36080 			duk__enc_key_autoquote(js_ctx, h_key);
36081 			DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36082 		}
36083 
36084 		/* [ ... key ] */
36085 
36086 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_obj) == 0)) {
36087 			/* Value would yield 'undefined', so skip key altogether.
36088 			 * Side effects have already happened.
36089 			 */
36090 			DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36091 		} else {
36092 			DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36093 			emitted = 1;
36094 		}
36095 
36096 		/* [ ... ] */
36097 	}
36098 
36099 	if (emitted) {
36100 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36101 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36102 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36103 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36104 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36105 		}
36106 	}
36107 	DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36108 
36109 	duk__enc_objarr_exit(js_ctx, &entry_top);
36110 
36111 	DUK_ASSERT_TOP(thr, entry_top);
36112 }
36113 
36114 /* The JA(value) operation: encode array.
36115  *
36116  * Stack policy: [ array ] -> [ array ].
36117  */
36118 DUK_LOCAL void duk__enc_array(duk_json_enc_ctx *js_ctx) {
36119 	duk_hthread *thr = js_ctx->thr;
36120 	duk_idx_t entry_top;
36121 	duk_idx_t idx_arr;
36122 	duk_bool_t emitted;
36123 	duk_uarridx_t i, arr_len;
36124 
36125 	DUK_DDD(DUK_DDDPRINT("duk__enc_array: array=%!T",
36126 	                     (duk_tval *) duk_get_tval(thr, -1)));
36127 
36128 	duk__enc_objarr_entry(js_ctx, &entry_top);
36129 
36130 	idx_arr = entry_top - 1;
36131 
36132 	/* Steps 8-10 have been merged to avoid a "partial" variable. */
36133 
36134 	DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36135 
36136 	arr_len = (duk_uarridx_t) duk_get_length(thr, idx_arr);
36137 	emitted = 0;
36138 	for (i = 0; i < arr_len; i++) {
36139 		DUK_DDD(DUK_DDDPRINT("array entry loop: array=%!T, index=%ld, arr_len=%ld",
36140 		                     (duk_tval *) duk_get_tval(thr, idx_arr),
36141 		                     (long) i, (long) arr_len));
36142 
36143 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36144 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36145 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36146 		}
36147 
36148 		(void) duk_push_uint_to_hstring(thr, (duk_uint_t) i);  /* -> [ ... key ] */
36149 
36150 		/* [ ... key ] */
36151 
36152 		if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_arr) == 0)) {
36153 			/* Value would normally be omitted, replace with 'null'. */
36154 			DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36155 		} else {
36156 			;
36157 		}
36158 
36159 		/* [ ... ] */
36160 
36161 		DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36162 		emitted = 1;
36163 	}
36164 
36165 	if (emitted) {
36166 		DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36167 		DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36168 		if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36169 			DUK_ASSERT(js_ctx->recursion_depth >= 1);
36170 			duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36171 		}
36172 	}
36173 	DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36174 
36175 	duk__enc_objarr_exit(js_ctx, &entry_top);
36176 
36177 	DUK_ASSERT_TOP(thr, entry_top);
36178 }
36179 
36180 /* The Str(key, holder) operation.
36181  *
36182  * Stack policy: [ ... key ] -> [ ... ]
36183  */
36184 DUK_LOCAL duk_bool_t duk__enc_value(duk_json_enc_ctx *js_ctx, duk_idx_t idx_holder) {
36185 	duk_hthread *thr = js_ctx->thr;
36186 	duk_tval *tv;
36187 	duk_tval *tv_holder;
36188 	duk_tval *tv_key;
36189 	duk_small_int_t c;
36190 
36191 	DUK_DDD(DUK_DDDPRINT("duk__enc_value: idx_holder=%ld, holder=%!T, key=%!T",
36192 	                     (long) idx_holder, (duk_tval *) duk_get_tval(thr, idx_holder),
36193 	                     (duk_tval *) duk_get_tval(thr, -1)));
36194 
36195 	tv_holder = DUK_GET_TVAL_POSIDX(thr, idx_holder);
36196 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_holder));
36197 	tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
36198 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_key));
36199 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(DUK_TVAL_GET_STRING(tv_key)));  /* Caller responsible. */
36200 	(void) duk_hobject_getprop(thr, tv_holder, tv_key);
36201 
36202 	/* -> [ ... key val ] */
36203 
36204 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36205 
36206 	/* Standard JSON checks for .toJSON() only for actual objects; for
36207 	 * example, setting Number.prototype.toJSON and then serializing a
36208 	 * number won't invoke the .toJSON() method.  However, lightfuncs and
36209 	 * plain buffers mimic objects so we check for their .toJSON() method.
36210 	 */
36211 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
36212 	                                 DUK_TYPE_MASK_LIGHTFUNC |
36213 	                                 DUK_TYPE_MASK_BUFFER)) {
36214 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_TO_JSON);
36215 		if (duk_is_callable(thr, -1)) {  /* toJSON() can also be a lightfunc */
36216 			DUK_DDD(DUK_DDDPRINT("value is object, has callable toJSON() -> call it"));
36217 			/* XXX: duk_dup_unvalidated(thr, -2) etc. */
36218 			duk_dup_m2(thr);          /* -> [ ... key val toJSON val ] */
36219 			duk_dup_m4(thr);          /* -> [ ... key val toJSON val key ] */
36220 			duk_call_method(thr, 1);  /* -> [ ... key val val' ] */
36221 			duk_remove_m2(thr);       /* -> [ ... key val' ] */
36222 		} else {
36223 			duk_pop(thr);             /* -> [ ... key val ] */
36224 		}
36225 	}
36226 
36227 	/* [ ... key val ] */
36228 
36229 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36230 
36231 	if (js_ctx->h_replacer) {
36232 		/* XXX: Here a "slice copy" would be useful. */
36233 		DUK_DDD(DUK_DDDPRINT("replacer is set, call replacer"));
36234 		duk_push_hobject(thr, js_ctx->h_replacer);  /* -> [ ... key val replacer ] */
36235 		duk_dup(thr, idx_holder);                   /* -> [ ... key val replacer holder ] */
36236 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key ] */
36237 		duk_dup_m4(thr);                            /* -> [ ... key val replacer holder key val ] */
36238 		duk_call_method(thr, 2);                    /* -> [ ... key val val' ] */
36239 		duk_remove_m2(thr);                         /* -> [ ... key val' ] */
36240 	}
36241 
36242 	/* [ ... key val ] */
36243 
36244 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36245 
36246 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36247 	if (DUK_TVAL_IS_OBJECT(tv)) {
36248 		duk_hobject *h;
36249 
36250 		h = DUK_TVAL_GET_OBJECT(tv);
36251 		DUK_ASSERT(h != NULL);
36252 
36253 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36254 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36255 		if (DUK_HOBJECT_IS_BUFOBJ(h) &&
36256 		    js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36257 			/* With JX/JC a bufferobject gets serialized specially. */
36258 			duk_hbufobj *h_bufobj;
36259 			h_bufobj = (duk_hbufobj *) h;
36260 			DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
36261 			duk__enc_bufobj(js_ctx, h_bufobj);
36262 			goto pop2_emitted;
36263 		}
36264 		/* Otherwise bufferobjects get serialized as normal objects. */
36265 #endif  /* JX || JC */
36266 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
36267 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36268 		switch (c) {
36269 		case DUK_HOBJECT_CLASS_NUMBER: {
36270 			DUK_DDD(DUK_DDDPRINT("value is a Number object -> coerce with ToNumber()"));
36271 			duk_to_number_m1(thr);
36272 			/* The coercion potentially invokes user .valueOf() and .toString()
36273 			 * but can't result in a function value because ToPrimitive() would
36274 			 * reject such a result: test-dev-json-stringify-coercion-1.js.
36275 			 */
36276 			DUK_ASSERT(!duk_is_callable(thr, -1));
36277 			break;
36278 		}
36279 		case DUK_HOBJECT_CLASS_STRING: {
36280 			DUK_DDD(DUK_DDDPRINT("value is a String object -> coerce with ToString()"));
36281 			duk_to_string(thr, -1);
36282 			/* Same coercion behavior as for Number. */
36283 			DUK_ASSERT(!duk_is_callable(thr, -1));
36284 			break;
36285 		}
36286 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36287 		case DUK_HOBJECT_CLASS_POINTER:
36288 #endif
36289 		case DUK_HOBJECT_CLASS_BOOLEAN: {
36290 			DUK_DDD(DUK_DDDPRINT("value is a Boolean/Buffer/Pointer object -> get internal value"));
36291 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
36292 			duk_remove_m2(thr);
36293 			break;
36294 		}
36295 		default: {
36296 			/* Normal object which doesn't get automatically coerced to a
36297 			 * primitive value.  Functions are checked for specially.  The
36298 			 * primitive value coercions for Number, String, Pointer, and
36299 			 * Boolean can't result in functions so suffices to check here.
36300 			 * Symbol objects are handled like plain objects (their primitive
36301 			 * value is NOT looked up like for e.g. String objects).
36302 			 */
36303 			DUK_ASSERT(h != NULL);
36304 			if (DUK_HOBJECT_IS_CALLABLE(h)) {
36305 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36306 				if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
36307 				                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
36308 					/* We only get here when doing non-standard JSON encoding */
36309 					DUK_DDD(DUK_DDDPRINT("-> function allowed, serialize to custom format"));
36310 					DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36311 					DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36312 					goto pop2_emitted;
36313 				} else {
36314 					DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36315 					goto pop2_undef;
36316 				}
36317 #else  /* DUK_USE_JX || DUK_USE_JC */
36318 				DUK_DDD(DUK_DDDPRINT("-> will result in undefined (function)"));
36319 				goto pop2_undef;
36320 #endif  /* DUK_USE_JX || DUK_USE_JC */
36321 			}
36322 		}
36323 		}  /* end switch */
36324 	}
36325 
36326 	/* [ ... key val ] */
36327 
36328 	DUK_DDD(DUK_DDDPRINT("value=%!T", (duk_tval *) duk_get_tval(thr, -1)));
36329 
36330 	if (duk_check_type_mask(thr, -1, js_ctx->mask_for_undefined)) {
36331 		/* will result in undefined */
36332 		DUK_DDD(DUK_DDDPRINT("-> will result in undefined (type mask check)"));
36333 		goto pop2_undef;
36334 	}
36335 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36336 
36337 	switch (DUK_TVAL_GET_TAG(tv)) {
36338 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36339 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36340 	case DUK_TAG_UNDEFINED: {
36341 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36342 		break;
36343 	}
36344 #endif
36345 	case DUK_TAG_NULL: {
36346 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36347 		break;
36348 	}
36349 	case DUK_TAG_BOOLEAN: {
36350 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36351 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36352 		break;
36353 	}
36354 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36355 	/* When JX/JC not in use, the type mask above will avoid this case if needed. */
36356 	case DUK_TAG_POINTER: {
36357 		duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
36358 		break;
36359 	}
36360 #endif  /* DUK_USE_JX || DUK_USE_JC */
36361 	case DUK_TAG_STRING: {
36362 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
36363 		DUK_ASSERT(h != NULL);
36364 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36365 			goto pop2_undef;
36366 		}
36367 		duk__enc_quote_string(js_ctx, h);
36368 		break;
36369 	}
36370 	case DUK_TAG_OBJECT: {
36371 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
36372 		DUK_ASSERT(h != NULL);
36373 
36374 		/* Function values are handled completely above (including
36375 		 * coercion results):
36376 		 */
36377 		DUK_ASSERT(!DUK_HOBJECT_IS_CALLABLE(h));
36378 
36379 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
36380 			duk__enc_array(js_ctx);
36381 		} else {
36382 			duk__enc_object(js_ctx);
36383 		}
36384 		break;
36385 	}
36386 	/* Because plain buffers mimics Uint8Array, they have enumerable
36387 	 * index properties [0,byteLength[.  Because JSON only serializes
36388 	 * enumerable own properties, no properties can be serialized for
36389 	 * plain buffers (all virtual properties are non-enumerable).  However,
36390 	 * there may be a .toJSON() method which was already handled above.
36391 	 */
36392 	case DUK_TAG_BUFFER: {
36393 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36394 		if (js_ctx->flag_ext_custom_or_compatible) {
36395 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36396 			break;
36397 		}
36398 #endif
36399 
36400 		/* Could implement a fastpath, but the fast path would need
36401 		 * to handle realloc side effects correctly.
36402 		 */
36403 		duk_to_object(thr, -1);
36404 		duk__enc_object(js_ctx);
36405 		break;
36406 	}
36407 	case DUK_TAG_LIGHTFUNC: {
36408 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36409 		/* We only get here when doing non-standard JSON encoding */
36410 		DUK_ASSERT(js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible);
36411 		DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36412 #else
36413 		/* Standard JSON omits functions */
36414 		DUK_UNREACHABLE();
36415 #endif
36416 		break;
36417 	}
36418 #if defined(DUK_USE_FASTINT)
36419 	case DUK_TAG_FASTINT:
36420 		/* Number serialization has a significant impact relative to
36421 		 * other fast path code, so careful fast path for fastints.
36422 		 */
36423 		duk__enc_fastint_tval(js_ctx, tv);
36424 		break;
36425 #endif
36426 	default: {
36427 		/* number */
36428 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36429 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36430 		/* XXX: A fast path for usual integers would be useful when
36431 		 * fastint support is not enabled.
36432 		 */
36433 		duk__enc_double(js_ctx);
36434 		break;
36435 	}
36436 	}
36437 
36438 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36439  pop2_emitted:
36440 #endif
36441 	duk_pop_2(thr); /* [ ... key val ] -> [ ... ] */
36442 	return 1;  /* emitted */
36443 
36444  pop2_undef:
36445 	duk_pop_2(thr);  /* [ ... key val ] -> [ ... ] */
36446 	return 0;  /* not emitted */
36447 }
36448 
36449 /* E5 Section 15.12.3, main algorithm, step 4.b.ii steps 1-4. */
36450 DUK_LOCAL duk_bool_t duk__enc_allow_into_proplist(duk_tval *tv) {
36451 	duk_small_int_t c;
36452 
36453 	/* XXX: some kind of external internal type checker?
36454 	 * - type mask; symbol flag; class mask
36455 	 */
36456 	DUK_ASSERT(tv != NULL);
36457 	if (DUK_TVAL_IS_STRING(tv)) {
36458 		duk_hstring *h;
36459 		h = DUK_TVAL_GET_STRING(tv);
36460 		DUK_ASSERT(h != NULL);
36461 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36462 			return 0;
36463 		}
36464 		return 1;
36465 	} else if (DUK_TVAL_IS_NUMBER(tv)) {
36466 		return 1;
36467 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
36468 		duk_hobject *h;
36469 		h = DUK_TVAL_GET_OBJECT(tv);
36470 		DUK_ASSERT(h != NULL);
36471 		c = (duk_small_int_t) DUK_HOBJECT_GET_CLASS_NUMBER(h);
36472 		if (c == DUK_HOBJECT_CLASS_STRING || c == DUK_HOBJECT_CLASS_NUMBER) {
36473 			return 1;
36474 		}
36475 	}
36476 
36477 	return 0;
36478 }
36479 
36480 /*
36481  *  JSON.stringify() fast path
36482  *
36483  *  Otherwise supports full JSON, JX, and JC features, but bails out on any
36484  *  possible side effect which might change the value being serialized.  The
36485  *  fast path can take advantage of the fact that the value being serialized
36486  *  is unchanged so that we can walk directly through property tables etc.
36487  */
36488 
36489 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
36490 DUK_LOCAL duk_bool_t duk__json_stringify_fast_value(duk_json_enc_ctx *js_ctx, duk_tval *tv) {
36491 	duk_uint_fast32_t i, n;
36492 
36493 	DUK_DDD(DUK_DDDPRINT("stringify fast: %!T", tv));
36494 
36495 	DUK_ASSERT(js_ctx != NULL);
36496 	DUK_ASSERT(js_ctx->thr != NULL);
36497 
36498 #if 0 /* disabled for now */
36499  restart_match:
36500 #endif
36501 
36502 	DUK_ASSERT(tv != NULL);
36503 
36504 	switch (DUK_TVAL_GET_TAG(tv)) {
36505 	case DUK_TAG_UNDEFINED: {
36506 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36507 		if (js_ctx->flag_ext_custom || js_ctx->flag_ext_compatible) {
36508 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36509 			break;
36510 		} else {
36511 			goto emit_undefined;
36512 		}
36513 #else
36514 		goto emit_undefined;
36515 #endif
36516 	}
36517 	case DUK_TAG_NULL: {
36518 		DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36519 		break;
36520 	}
36521 	case DUK_TAG_BOOLEAN: {
36522 		DUK__EMIT_STRIDX(js_ctx, DUK_TVAL_GET_BOOLEAN(tv) ?
36523 		                 DUK_STRIDX_TRUE : DUK_STRIDX_FALSE);
36524 		break;
36525 	}
36526 	case DUK_TAG_STRING: {
36527 		duk_hstring *h;
36528 		h = DUK_TVAL_GET_STRING(tv);
36529 		DUK_ASSERT(h != NULL);
36530 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
36531 			goto emit_undefined;
36532 		}
36533 		duk__enc_quote_string(js_ctx, h);
36534 		break;
36535 	}
36536 	case DUK_TAG_OBJECT: {
36537 		duk_hobject *obj;
36538 		duk_tval *tv_val;
36539 		duk_bool_t emitted = 0;
36540 		duk_uint32_t c_bit, c_all, c_array, c_unbox, c_undef,
36541 		             c_func, c_bufobj, c_object, c_abort;
36542 
36543 		/* For objects JSON.stringify() only looks for own, enumerable
36544 		 * properties which is nice for the fast path here.
36545 		 *
36546 		 * For arrays JSON.stringify() uses [[Get]] so it will actually
36547 		 * inherit properties during serialization!  This fast path
36548 		 * supports gappy arrays as long as there's no actual inherited
36549 		 * property (which might be a getter etc).
36550 		 *
36551 		 * Since recursion only happens for objects, we can have both
36552 		 * recursion and loop checks here.  We use a simple, depth-limited
36553 		 * loop check in the fast path because the object-based tracking
36554 		 * is very slow (when tested, it accounted for 50% of fast path
36555 		 * execution time for input data with a lot of small objects!).
36556 		 */
36557 
36558 		/* XXX: for real world code, could just ignore array inheritance
36559 		 * and only look at array own properties.
36560 		 */
36561 
36562 		/* We rely on a few object flag / class number relationships here,
36563 		 * assert for them.
36564 		 */
36565 
36566 		obj = DUK_TVAL_GET_OBJECT(tv);
36567 		DUK_ASSERT(obj != NULL);
36568 		DUK_ASSERT_HOBJECT_VALID(obj);
36569 
36570 		/* Once recursion depth is increased, exit path must decrease
36571 		 * it (though it's OK to abort the fast path).
36572 		 */
36573 
36574 		DUK_ASSERT_DISABLE(js_ctx->recursion_depth >= 0);  /* unsigned */
36575 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36576 		if (js_ctx->recursion_depth >= js_ctx->recursion_limit) {
36577 			DUK_DD(DUK_DDPRINT("fast path recursion limit"));
36578 			DUK_ERROR_RANGE(js_ctx->thr, DUK_STR_JSONDEC_RECLIMIT);
36579 			DUK_WO_NORETURN(return 0;);
36580 		}
36581 
36582 		for (i = 0, n = (duk_uint_fast32_t) js_ctx->recursion_depth; i < n; i++) {
36583 			if (DUK_UNLIKELY(js_ctx->visiting[i] == obj)) {
36584 				DUK_DD(DUK_DDPRINT("fast path loop detect"));
36585 				DUK_ERROR_TYPE(js_ctx->thr, DUK_STR_CYCLIC_INPUT);
36586 				DUK_WO_NORETURN(return 0;);
36587 			}
36588 		}
36589 
36590 		/* Guaranteed by recursion_limit setup so we don't have to
36591 		 * check twice.
36592 		 */
36593 		DUK_ASSERT(js_ctx->recursion_depth < DUK_JSON_ENC_LOOPARRAY);
36594 		js_ctx->visiting[js_ctx->recursion_depth] = obj;
36595 		js_ctx->recursion_depth++;
36596 
36597 		/* If object has a .toJSON() property, we can't be certain
36598 		 * that it wouldn't mutate any value arbitrarily, so bail
36599 		 * out of the fast path.
36600 		 *
36601 		 * If an object is a Proxy we also can't avoid side effects
36602 		 * so abandon.
36603 		 */
36604 		/* XXX: non-callable .toJSON() doesn't need to cause an abort
36605 		 * but does at the moment, probably not worth fixing.
36606 		 */
36607 		if (duk_hobject_hasprop_raw(js_ctx->thr, obj, DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr)) ||
36608 		    DUK_HOBJECT_IS_PROXY(obj)) {
36609 			DUK_DD(DUK_DDPRINT("object has a .toJSON property or object is a Proxy, abort fast path"));
36610 			goto abort_fastpath;
36611 		}
36612 
36613 		/* We could use a switch-case for the class number but it turns out
36614 		 * a small if-else ladder on class masks is better.  The if-ladder
36615 		 * should be in order of relevancy.
36616 		 */
36617 
36618 		/* XXX: move masks to js_ctx? they don't change during one
36619 		 * fast path invocation.
36620 		 */
36621 		DUK_ASSERT(DUK_HOBJECT_CLASS_MAX <= 31);
36622 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36623 		if (js_ctx->flag_ext_custom_or_compatible) {
36624 			c_all = DUK_HOBJECT_CMASK_ALL;
36625 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36626 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36627 			          DUK_HOBJECT_CMASK_STRING |
36628 			          DUK_HOBJECT_CMASK_BOOLEAN |
36629 			          DUK_HOBJECT_CMASK_POINTER;  /* Symbols are not unboxed. */
36630 			c_func = DUK_HOBJECT_CMASK_FUNCTION;
36631 			c_bufobj = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36632 			c_undef = 0;
36633 			c_abort = 0;
36634 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36635 		}
36636 		else
36637 #endif
36638 		{
36639 			c_all = DUK_HOBJECT_CMASK_ALL;
36640 			c_array = DUK_HOBJECT_CMASK_ARRAY;
36641 			c_unbox = DUK_HOBJECT_CMASK_NUMBER |
36642 			          DUK_HOBJECT_CMASK_STRING |
36643 			          DUK_HOBJECT_CMASK_BOOLEAN;  /* Symbols are not unboxed. */
36644 			c_func = 0;
36645 			c_bufobj = 0;
36646 			c_undef = DUK_HOBJECT_CMASK_FUNCTION |
36647 			          DUK_HOBJECT_CMASK_POINTER;
36648 			/* As the fast path doesn't currently properly support
36649 			 * duk_hbufobj virtual properties, abort fast path if
36650 			 * we encounter them in plain JSON mode.
36651 			 */
36652 			c_abort = DUK_HOBJECT_CMASK_ALL_BUFOBJS;
36653 			c_object = c_all & ~(c_array | c_unbox | c_func | c_bufobj | c_undef | c_abort);
36654 		}
36655 
36656 		c_bit = (duk_uint32_t) DUK_HOBJECT_GET_CLASS_MASK(obj);
36657 		if (c_bit & c_object) {
36658 			/* All other object types. */
36659 			DUK__EMIT_1(js_ctx, DUK_ASC_LCURLY);
36660 
36661 			/* A non-Array object should not have an array part in practice.
36662 			 * But since it is supported internally (and perhaps used at some
36663 			 * point), check and abandon if that's the case.
36664 			 */
36665 			if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36666 				DUK_DD(DUK_DDPRINT("non-Array object has array part, abort fast path"));
36667 				goto abort_fastpath;
36668 			}
36669 
36670 			for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(obj); i++) {
36671 				duk_hstring *k;
36672 				duk_size_t prev_size;
36673 
36674 				k = DUK_HOBJECT_E_GET_KEY(js_ctx->thr->heap, obj, i);
36675 				if (!k) {
36676 					continue;
36677 				}
36678 				if (DUK_HSTRING_HAS_ARRIDX(k)) {
36679 					/* If an object has array index keys we would need
36680 					 * to sort them into the ES2015 enumeration order to
36681 					 * be consistent with the slow path.  Abort the fast
36682 					 * path and handle in the slow path for now.
36683 					 */
36684 					DUK_DD(DUK_DDPRINT("property key is an array index, abort fast path"));
36685 					goto abort_fastpath;
36686 				}
36687 				if (!DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(js_ctx->thr->heap, obj, i)) {
36688 					continue;
36689 				}
36690 				if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(js_ctx->thr->heap, obj, i)) {
36691 					/* Getter might have arbitrary side effects,
36692 					 * so bail out.
36693 					 */
36694 					DUK_DD(DUK_DDPRINT("property is an accessor, abort fast path"));
36695 					goto abort_fastpath;
36696 				}
36697 				if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
36698 					continue;
36699 				}
36700 
36701 				tv_val = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(js_ctx->thr->heap, obj, i);
36702 
36703 				prev_size = DUK_BW_GET_SIZE(js_ctx->thr, &js_ctx->bw);
36704 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36705 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36706 					duk__enc_key_autoquote(js_ctx, k);
36707 					DUK__EMIT_2(js_ctx, DUK_ASC_COLON, DUK_ASC_SPACE);
36708 				} else {
36709 					duk__enc_key_autoquote(js_ctx, k);
36710 					DUK__EMIT_1(js_ctx, DUK_ASC_COLON);
36711 				}
36712 
36713 				if (duk__json_stringify_fast_value(js_ctx, tv_val) == 0) {
36714 					DUK_DD(DUK_DDPRINT("prop value not supported, rewind key and colon"));
36715 					DUK_BW_SET_SIZE(js_ctx->thr, &js_ctx->bw, prev_size);
36716 				} else {
36717 					DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36718 					emitted = 1;
36719 				}
36720 			}
36721 
36722 			/* If any non-Array value had enumerable virtual own
36723 			 * properties, they should be serialized here (actually,
36724 			 * before the explicit properties).  Standard types don't.
36725 			 */
36726 
36727 			if (emitted) {
36728 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36729 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36730 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36731 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36732 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36733 				}
36734 			}
36735 			DUK__EMIT_1(js_ctx, DUK_ASC_RCURLY);
36736 		} else if (c_bit & c_array) {
36737 			duk_uint_fast32_t arr_len;
36738 			duk_uint_fast32_t asize;
36739 
36740 			DUK__EMIT_1(js_ctx, DUK_ASC_LBRACKET);
36741 
36742 			/* Assume arrays are dense in the fast path. */
36743 			if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
36744 				DUK_DD(DUK_DDPRINT("Array object is sparse, abort fast path"));
36745 				goto abort_fastpath;
36746 			}
36747 
36748 			arr_len = (duk_uint_fast32_t) ((duk_harray *) obj)->length;
36749 			asize = (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(obj);
36750 			/* Array part may be larger than 'length'; if so, iterate
36751 			 * only up to array 'length'.  Array part may also be smaller
36752 			 * than 'length' in some cases.
36753 			 */
36754 			for (i = 0; i < arr_len; i++) {
36755 				duk_tval *tv_arrval;
36756 				duk_hstring *h_tmp;
36757 				duk_bool_t has_inherited;
36758 
36759 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36760 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth);
36761 				}
36762 
36763 				if (DUK_LIKELY(i < asize)) {
36764 					tv_arrval = DUK_HOBJECT_A_GET_VALUE_PTR(js_ctx->thr->heap, obj, i);
36765 					if (DUK_LIKELY(!DUK_TVAL_IS_UNUSED(tv_arrval))) {
36766 						/* Expected case: element is present. */
36767 						if (duk__json_stringify_fast_value(js_ctx, tv_arrval) == 0) {
36768 							DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36769 						}
36770 						goto elem_done;
36771 					}
36772 				}
36773 
36774 				/* Gap in array; check for inherited property,
36775 				 * bail out if one exists.  This should be enough
36776 				 * to support gappy arrays for all practical code.
36777 				 */
36778 
36779 				h_tmp = duk_push_uint_to_hstring(js_ctx->thr, (duk_uint_t) i);
36780 				has_inherited = duk_hobject_hasprop_raw(js_ctx->thr, obj, h_tmp);
36781 				duk_pop(js_ctx->thr);
36782 				if (has_inherited) {
36783 					DUK_D(DUK_DPRINT("gap in array, conflicting inherited property, abort fast path"));
36784 					goto abort_fastpath;
36785 				}
36786 
36787 				/* Ordinary gap, undefined encodes to 'null' in
36788 				 * standard JSON, but JX/JC use their form for
36789 				 * undefined to better preserve the typing.
36790 				 */
36791 				DUK_D(DUK_DPRINT("gap in array, no conflicting inherited property, remain on fast path"));
36792 #if defined(DUK_USE_JX)
36793 				DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_undefined);
36794 #else
36795 				DUK__EMIT_STRIDX(js_ctx, DUK_STRIDX_LC_NULL);
36796 #endif
36797 				/* fall through */
36798 
36799 			 elem_done:
36800 				DUK__EMIT_1(js_ctx, DUK_ASC_COMMA);
36801 				emitted = 1;
36802 			}
36803 
36804 			if (emitted) {
36805 				DUK_ASSERT(*((duk_uint8_t *) DUK_BW_GET_PTR(js_ctx->thr, &js_ctx->bw) - 1) == DUK_ASC_COMMA);
36806 				DUK__UNEMIT_1(js_ctx);  /* eat trailing comma */
36807 				if (DUK_UNLIKELY(js_ctx->h_gap != NULL)) {
36808 					DUK_ASSERT(js_ctx->recursion_depth >= 1);
36809 					duk__enc_newline_indent(js_ctx, js_ctx->recursion_depth - 1U);
36810 				}
36811 			}
36812 			DUK__EMIT_1(js_ctx, DUK_ASC_RBRACKET);
36813 		} else if (c_bit & c_unbox) {
36814 			/* Certain boxed types are required to go through
36815 			 * automatic unboxing.  Rely on internal value being
36816 			 * sane (to avoid infinite recursion).
36817 			 */
36818 			DUK_ASSERT((c_bit & DUK_HOBJECT_CMASK_SYMBOL) == 0);  /* Symbols are not unboxed. */
36819 
36820 #if 1
36821 			/* The code below is incorrect if .toString() or .valueOf() have
36822 			 * have been overridden.  The correct approach would be to look up
36823 			 * the method(s) and if they resolve to the built-in function we
36824 			 * can safely bypass it and look up the internal value directly.
36825 			 * Unimplemented for now, abort fast path for boxed values.
36826 			 */
36827 			goto abort_fastpath;
36828 #else  /* disabled */
36829 			/* Disabled until fixed, see above. */
36830 			duk_tval *tv_internal;
36831 
36832 			DUK_DD(DUK_DDPRINT("auto unboxing in fast path"));
36833 
36834 			tv_internal = duk_hobject_get_internal_value_tval_ptr(js_ctx->thr->heap, obj);
36835 			DUK_ASSERT(tv_internal != NULL);
36836 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv_internal) ||
36837 			           DUK_TVAL_IS_NUMBER(tv_internal) ||
36838 			           DUK_TVAL_IS_BOOLEAN(tv_internal) ||
36839 			           DUK_TVAL_IS_POINTER(tv_internal));
36840 
36841 			tv = tv_internal;
36842 			DUK_ASSERT(js_ctx->recursion_depth > 0);
36843 			js_ctx->recursion_depth--;  /* required to keep recursion depth correct */
36844 			goto restart_match;
36845 #endif  /* disabled */
36846 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36847 		} else if (c_bit & c_func) {
36848 			DUK__EMIT_STRIDX(js_ctx, js_ctx->stridx_custom_function);
36849 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36850 		} else if (c_bit & c_bufobj) {
36851 			duk__enc_bufobj(js_ctx, (duk_hbufobj *) obj);
36852 #endif
36853 #endif
36854 		} else if (c_bit & c_abort) {
36855 			DUK_DD(DUK_DDPRINT("abort fast path for unsupported type"));
36856 			goto abort_fastpath;
36857 		} else {
36858 			DUK_ASSERT((c_bit & c_undef) != 0);
36859 
36860 			/* Must decrease recursion depth before returning. */
36861 			DUK_ASSERT(js_ctx->recursion_depth > 0);
36862 			DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36863 			js_ctx->recursion_depth--;
36864 			goto emit_undefined;
36865 		}
36866 
36867 		DUK_ASSERT(js_ctx->recursion_depth > 0);
36868 		DUK_ASSERT(js_ctx->recursion_depth <= js_ctx->recursion_limit);
36869 		js_ctx->recursion_depth--;
36870 		break;
36871 	}
36872 	case DUK_TAG_BUFFER: {
36873 		/* Plain buffers are treated like Uint8Arrays: they have
36874 		 * enumerable indices.  Other virtual properties are not
36875 		 * enumerable, and inherited properties are not serialized.
36876 		 * However, there can be a replacer (not relevant here) or
36877 		 * a .toJSON() method (which we need to check for explicitly).
36878 		 */
36879 
36880 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
36881 		if (duk_hobject_hasprop_raw(js_ctx->thr,
36882 		                            js_ctx->thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE],
36883 		                            DUK_HTHREAD_STRING_TO_JSON(js_ctx->thr))) {
36884 			DUK_DD(DUK_DDPRINT("value is a plain buffer and there's an inherited .toJSON, abort fast path"));
36885 			goto abort_fastpath;
36886 		}
36887 #endif
36888 
36889 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36890 		if (js_ctx->flag_ext_custom_or_compatible) {
36891 			duk__enc_buffer_jx_jc(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36892 			break;
36893 		}
36894 #endif
36895 
36896 		/* Plain buffers mimic Uint8Arrays, and have enumerable index
36897 		 * properties.
36898 		 */
36899 		duk__enc_buffer_json_fastpath(js_ctx, DUK_TVAL_GET_BUFFER(tv));
36900 		break;
36901 	}
36902 	case DUK_TAG_POINTER: {
36903 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
36904 		if (js_ctx->flag_ext_custom_or_compatible) {
36905 			duk__enc_pointer(js_ctx, DUK_TVAL_GET_POINTER(tv));
36906 			break;
36907 		} else {
36908 			goto emit_undefined;
36909 		}
36910 #else
36911 		goto emit_undefined;
36912 #endif
36913 	}
36914 	case DUK_TAG_LIGHTFUNC: {
36915 		/* A lightfunc might also inherit a .toJSON() so just bail out. */
36916 		/* XXX: Could just lookup .toJSON() and continue in fast path,
36917 		 * as it would almost never be defined.
36918 		 */
36919 		DUK_DD(DUK_DDPRINT("value is a lightfunc, abort fast path"));
36920 		goto abort_fastpath;
36921 	}
36922 #if defined(DUK_USE_FASTINT)
36923 	case DUK_TAG_FASTINT: {
36924 		/* Number serialization has a significant impact relative to
36925 		 * other fast path code, so careful fast path for fastints.
36926 		 */
36927 		duk__enc_fastint_tval(js_ctx, tv);
36928 		break;
36929 	}
36930 #endif
36931 	default: {
36932 		/* XXX: A fast path for usual integers would be useful when
36933 		 * fastint support is not enabled.
36934 		 */
36935 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
36936 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
36937 
36938 		/* XXX: Stack discipline is annoying, could be changed in numconv. */
36939 		duk_push_tval(js_ctx->thr, tv);
36940 		duk__enc_double(js_ctx);
36941 		duk_pop(js_ctx->thr);
36942 
36943 #if 0
36944 		/* Could also rely on native sprintf(), but it will handle
36945 		 * values like NaN, Infinity, -0, exponent notation etc in
36946 		 * a JSON-incompatible way.
36947 		 */
36948 		duk_double_t d;
36949 		char buf[64];
36950 
36951 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
36952 		d = DUK_TVAL_GET_DOUBLE(tv);
36953 		DUK_SPRINTF(buf, "%lg", d);
36954 		DUK__EMIT_CSTR(js_ctx, buf);
36955 #endif
36956 	}
36957 	}
36958 	return 1;  /* not undefined */
36959 
36960  emit_undefined:
36961 	return 0;  /* value was undefined/unsupported */
36962 
36963  abort_fastpath:
36964 	/* Error message doesn't matter: the error is ignored anyway. */
36965 	DUK_DD(DUK_DDPRINT("aborting fast path"));
36966 	DUK_ERROR_INTERNAL(js_ctx->thr);
36967 	DUK_WO_NORETURN(return 0;);
36968 }
36969 
36970 DUK_LOCAL duk_ret_t duk__json_stringify_fast(duk_hthread *thr, void *udata) {
36971 	duk_json_enc_ctx *js_ctx;
36972 	duk_tval *tv;
36973 
36974 	DUK_ASSERT(thr != NULL);
36975 	DUK_ASSERT(udata != NULL);
36976 
36977 	js_ctx = (duk_json_enc_ctx *) udata;
36978 	DUK_ASSERT(js_ctx != NULL);
36979 
36980 	tv = DUK_GET_TVAL_NEGIDX(thr, -1);
36981 	if (duk__json_stringify_fast_value(js_ctx, tv) == 0) {
36982 		DUK_DD(DUK_DDPRINT("top level value not supported, fail fast path"));
36983 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);  /* Error message is ignored, so doesn't matter. */
36984 	}
36985 
36986 	return 0;
36987 }
36988 #endif  /* DUK_USE_JSON_STRINGIFY_FASTPATH */
36989 
36990 /*
36991  *  Top level wrappers
36992  */
36993 
36994 DUK_INTERNAL
36995 void duk_bi_json_parse_helper(duk_hthread *thr,
36996                               duk_idx_t idx_value,
36997                               duk_idx_t idx_reviver,
36998                               duk_small_uint_t flags) {
36999 	duk_json_dec_ctx js_ctx_alloc;
37000 	duk_json_dec_ctx *js_ctx = &js_ctx_alloc;
37001 	duk_hstring *h_text;
37002 #if defined(DUK_USE_ASSERTIONS)
37003 	duk_idx_t entry_top = duk_get_top(thr);
37004 #endif
37005 
37006 	/* negative top-relative indices not allowed now */
37007 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37008 	DUK_ASSERT(idx_reviver == DUK_INVALID_INDEX || idx_reviver >= 0);
37009 
37010 	DUK_DDD(DUK_DDDPRINT("JSON parse start: text=%!T, reviver=%!T, flags=0x%08lx, stack_top=%ld",
37011 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37012 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37013 	                     (unsigned long) flags,
37014 	                     (long) duk_get_top(thr)));
37015 
37016 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37017 	js_ctx->thr = thr;
37018 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37019 	/* nothing now */
37020 #endif
37021 	js_ctx->recursion_limit = DUK_USE_JSON_DEC_RECLIMIT;
37022 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37023 
37024 	/* Flag handling currently assumes that flags are consistent.  This is OK
37025 	 * because the call sites are now strictly controlled.
37026 	 */
37027 
37028 	js_ctx->flags = flags;
37029 #if defined(DUK_USE_JX)
37030 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37031 #endif
37032 #if defined(DUK_USE_JC)
37033 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37034 #endif
37035 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37036 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37037 #endif
37038 
37039 	h_text = duk_to_hstring(thr, idx_value);  /* coerce in-place; rejects Symbols */
37040 	DUK_ASSERT(h_text != NULL);
37041 
37042 	/* JSON parsing code is allowed to read [p_start,p_end]: p_end is
37043 	 * valid and points to the string NUL terminator (which is always
37044 	 * guaranteed for duk_hstrings.
37045 	 */
37046 	js_ctx->p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text);
37047 	js_ctx->p = js_ctx->p_start;
37048 	js_ctx->p_end = ((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_text)) +
37049 	                DUK_HSTRING_GET_BYTELEN(h_text);
37050 	DUK_ASSERT(*(js_ctx->p_end) == 0x00);
37051 
37052 	duk__dec_value(js_ctx);  /* -> [ ... value ] */
37053 
37054 	/* Trailing whitespace has been eaten by duk__dec_value(), so if
37055 	 * we're not at end of input here, it's a SyntaxError.
37056 	 */
37057 
37058 	if (js_ctx->p != js_ctx->p_end) {
37059 		duk__dec_syntax_error(js_ctx);
37060 	}
37061 
37062 	if (duk_is_callable(thr, idx_reviver)) {
37063 		DUK_DDD(DUK_DDDPRINT("applying reviver: %!T",
37064 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37065 
37066 		js_ctx->idx_reviver = idx_reviver;
37067 
37068 		duk_push_object(thr);
37069 		duk_dup_m2(thr);  /* -> [ ... val root val ] */
37070 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);  /* default attrs ok */
37071 		duk_push_hstring_stridx(thr, DUK_STRIDX_EMPTY_STRING);  /* -> [ ... val root "" ] */
37072 
37073 		DUK_DDD(DUK_DDDPRINT("start reviver walk, root=%!T, name=%!T",
37074 		                     (duk_tval *) duk_get_tval(thr, -2),
37075 		                     (duk_tval *) duk_get_tval(thr, -1)));
37076 
37077 		duk__dec_reviver_walk(js_ctx);  /* [ ... val root "" ] -> [ ... val val' ] */
37078 		duk_remove_m2(thr);             /* -> [ ... val' ] */
37079 	} else {
37080 		DUK_DDD(DUK_DDDPRINT("reviver does not exist or is not callable: %!T",
37081 		                     (duk_tval *) duk_get_tval(thr, idx_reviver)));
37082 	}
37083 
37084 	/* Final result is at stack top. */
37085 
37086 	DUK_DDD(DUK_DDDPRINT("JSON parse end: text=%!T, reviver=%!T, flags=0x%08lx, result=%!T, stack_top=%ld",
37087 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37088 	                     (duk_tval *) duk_get_tval(thr, idx_reviver),
37089 	                     (unsigned long) flags,
37090 	                     (duk_tval *) duk_get_tval(thr, -1),
37091 	                     (long) duk_get_top(thr)));
37092 
37093 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37094 }
37095 
37096 DUK_INTERNAL
37097 void duk_bi_json_stringify_helper(duk_hthread *thr,
37098                                   duk_idx_t idx_value,
37099                                   duk_idx_t idx_replacer,
37100                                   duk_idx_t idx_space,
37101                                   duk_small_uint_t flags) {
37102 	duk_json_enc_ctx js_ctx_alloc;
37103 	duk_json_enc_ctx *js_ctx = &js_ctx_alloc;
37104 	duk_hobject *h;
37105 	duk_idx_t idx_holder;
37106 	duk_idx_t entry_top;
37107 
37108 	/* negative top-relative indices not allowed now */
37109 	DUK_ASSERT(idx_value == DUK_INVALID_INDEX || idx_value >= 0);
37110 	DUK_ASSERT(idx_replacer == DUK_INVALID_INDEX || idx_replacer >= 0);
37111 	DUK_ASSERT(idx_space == DUK_INVALID_INDEX || idx_space >= 0);
37112 
37113 	DUK_DDD(DUK_DDDPRINT("JSON stringify start: value=%!T, replacer=%!T, space=%!T, flags=0x%08lx, stack_top=%ld",
37114 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37115 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37116 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37117 	                     (unsigned long) flags,
37118 	                     (long) duk_get_top(thr)));
37119 
37120 	entry_top = duk_get_top(thr);
37121 
37122 	/*
37123 	 *  Context init
37124 	 */
37125 
37126 	duk_memzero(&js_ctx_alloc, sizeof(js_ctx_alloc));
37127 	js_ctx->thr = thr;
37128 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
37129 	js_ctx->h_replacer = NULL;
37130 	js_ctx->h_gap = NULL;
37131 #endif
37132 	js_ctx->idx_proplist = -1;
37133 
37134 	/* Flag handling currently assumes that flags are consistent.  This is OK
37135 	 * because the call sites are now strictly controlled.
37136 	 */
37137 
37138 	js_ctx->flags = flags;
37139 	js_ctx->flag_ascii_only = flags & DUK_JSON_FLAG_ASCII_ONLY;
37140 	js_ctx->flag_avoid_key_quotes = flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES;
37141 #if defined(DUK_USE_JX)
37142 	js_ctx->flag_ext_custom = flags & DUK_JSON_FLAG_EXT_CUSTOM;
37143 #endif
37144 #if defined(DUK_USE_JC)
37145 	js_ctx->flag_ext_compatible = flags & DUK_JSON_FLAG_EXT_COMPATIBLE;
37146 #endif
37147 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37148 	js_ctx->flag_ext_custom_or_compatible = flags & (DUK_JSON_FLAG_EXT_CUSTOM | DUK_JSON_FLAG_EXT_COMPATIBLE);
37149 #endif
37150 
37151 	/* The #if defined() clutter here handles the JX/JC enable/disable
37152 	 * combinations properly.
37153 	 */
37154 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37155 	js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_NULL;  /* standard JSON; array gaps */
37156 #if defined(DUK_USE_JX)
37157 	if (flags & DUK_JSON_FLAG_EXT_CUSTOM) {
37158 		js_ctx->stridx_custom_undefined = DUK_STRIDX_LC_UNDEFINED;
37159 		js_ctx->stridx_custom_nan = DUK_STRIDX_NAN;
37160 		js_ctx->stridx_custom_neginf = DUK_STRIDX_MINUS_INFINITY;
37161 		js_ctx->stridx_custom_posinf = DUK_STRIDX_INFINITY;
37162 		js_ctx->stridx_custom_function =
37163 		        (flags & DUK_JSON_FLAG_AVOID_KEY_QUOTES) ?
37164 		                DUK_STRIDX_JSON_EXT_FUNCTION2 :
37165 		                DUK_STRIDX_JSON_EXT_FUNCTION1;
37166 	}
37167 #endif  /* DUK_USE_JX */
37168 #if defined(DUK_USE_JX) && defined(DUK_USE_JC)
37169 	else
37170 #endif  /* DUK_USE_JX && DUK_USE_JC */
37171 #if defined(DUK_USE_JC)
37172 	if (js_ctx->flags & DUK_JSON_FLAG_EXT_COMPATIBLE) {
37173 		js_ctx->stridx_custom_undefined = DUK_STRIDX_JSON_EXT_UNDEFINED;
37174 		js_ctx->stridx_custom_nan = DUK_STRIDX_JSON_EXT_NAN;
37175 		js_ctx->stridx_custom_neginf = DUK_STRIDX_JSON_EXT_NEGINF;
37176 		js_ctx->stridx_custom_posinf = DUK_STRIDX_JSON_EXT_POSINF;
37177 		js_ctx->stridx_custom_function = DUK_STRIDX_JSON_EXT_FUNCTION1;
37178 	}
37179 #endif  /* DUK_USE_JC */
37180 #endif  /* DUK_USE_JX || DUK_USE_JC */
37181 
37182 #if defined(DUK_USE_JX) || defined(DUK_USE_JC)
37183 	if (js_ctx->flags & (DUK_JSON_FLAG_EXT_CUSTOM |
37184 	                     DUK_JSON_FLAG_EXT_COMPATIBLE)) {
37185 		DUK_ASSERT(js_ctx->mask_for_undefined == 0);  /* already zero */
37186 	}
37187 	else
37188 #endif  /* DUK_USE_JX || DUK_USE_JC */
37189 	{
37190 		/* Plain buffer is treated like ArrayBuffer and serialized.
37191 		 * Lightfuncs are treated like objects, but JSON explicitly
37192 		 * skips serializing Function objects so we can just reject
37193 		 * lightfuncs here.
37194 		 */
37195 		js_ctx->mask_for_undefined = DUK_TYPE_MASK_UNDEFINED |
37196 		                             DUK_TYPE_MASK_POINTER |
37197 		                             DUK_TYPE_MASK_LIGHTFUNC;
37198 	}
37199 
37200 	DUK_BW_INIT_PUSHBUF(thr, &js_ctx->bw, DUK__JSON_STRINGIFY_BUFSIZE);
37201 
37202 	js_ctx->idx_loop = duk_push_bare_object(thr);
37203 	DUK_ASSERT(js_ctx->idx_loop >= 0);
37204 
37205 	/* [ ... buf loop ] */
37206 
37207 	/*
37208 	 *  Process replacer/proplist (2nd argument to JSON.stringify)
37209 	 */
37210 
37211 	h = duk_get_hobject(thr, idx_replacer);
37212 	if (h != NULL) {
37213 		if (DUK_HOBJECT_IS_CALLABLE(h)) {
37214 			js_ctx->h_replacer = h;
37215 		} else if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_ARRAY) {
37216 			/* Here the specification requires correct array index enumeration
37217 			 * which is a bit tricky for sparse arrays (it is handled by the
37218 			 * enum setup code).  We now enumerate ancestors too, although the
37219 			 * specification is not very clear on whether that is required.
37220 			 */
37221 
37222 			duk_uarridx_t plist_idx = 0;
37223 			duk_small_uint_t enum_flags;
37224 
37225 			js_ctx->idx_proplist = duk_push_array(thr);  /* XXX: array internal? */
37226 
37227 			enum_flags = DUK_ENUM_ARRAY_INDICES_ONLY |
37228 			             DUK_ENUM_SORT_ARRAY_INDICES;  /* expensive flag */
37229 			duk_enum(thr, idx_replacer, enum_flags);
37230 			while (duk_next(thr, -1 /*enum_index*/, 1 /*get_value*/)) {
37231 				/* [ ... proplist enum_obj key val ] */
37232 				if (duk__enc_allow_into_proplist(duk_get_tval(thr, -1))) {
37233 					/* XXX: duplicates should be eliminated here */
37234 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> accept",
37235 					                     (duk_tval *) duk_get_tval(thr, -2),
37236 					                     (duk_tval *) duk_get_tval(thr, -1)));
37237 					duk_to_string(thr, -1);  /* extra coercion of strings is OK */
37238 					duk_put_prop_index(thr, -4, plist_idx);  /* -> [ ... proplist enum_obj key ] */
37239 					plist_idx++;
37240 					duk_pop(thr);
37241 				} else {
37242 					DUK_DDD(DUK_DDDPRINT("proplist enum: key=%!T, val=%!T --> reject",
37243 					                     (duk_tval *) duk_get_tval(thr, -2),
37244 					                     (duk_tval *) duk_get_tval(thr, -1)));
37245 					duk_pop_2(thr);
37246 				}
37247                         }
37248                         duk_pop(thr);  /* pop enum */
37249 
37250 			/* [ ... proplist ] */
37251 		}
37252 	}
37253 
37254 	/* [ ... buf loop (proplist) ] */
37255 
37256 	/*
37257 	 *  Process space (3rd argument to JSON.stringify)
37258 	 */
37259 
37260 	h = duk_get_hobject(thr, idx_space);
37261 	if (h != NULL) {
37262 		duk_small_uint_t c = DUK_HOBJECT_GET_CLASS_NUMBER(h);
37263 		if (c == DUK_HOBJECT_CLASS_NUMBER) {
37264 			duk_to_number(thr, idx_space);
37265 		} else if (c == DUK_HOBJECT_CLASS_STRING) {
37266 			duk_to_string(thr, idx_space);
37267 		}
37268 	}
37269 
37270 	if (duk_is_number(thr, idx_space)) {
37271 		duk_small_int_t nspace;
37272 		/* spaces[] must be static to allow initializer with old compilers like BCC */
37273 		static const char spaces[10] = {
37274 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37275 			DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE, DUK_ASC_SPACE,
37276 			DUK_ASC_SPACE, DUK_ASC_SPACE
37277 		};  /* XXX: helper */
37278 
37279 		/* ToInteger() coercion; NaN -> 0, infinities are clamped to 0 and 10 */
37280 		nspace = (duk_small_int_t) duk_to_int_clamped(thr, idx_space, 0 /*minval*/, 10 /*maxval*/);
37281 		DUK_ASSERT(nspace >= 0 && nspace <= 10);
37282 
37283 		duk_push_lstring(thr, spaces, (duk_size_t) nspace);
37284 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37285 		DUK_ASSERT(js_ctx->h_gap != NULL);
37286 	} else if (duk_is_string_notsymbol(thr, idx_space)) {
37287 		duk_dup(thr, idx_space);
37288 		duk_substring(thr, -1, 0, 10);  /* clamp to 10 chars */
37289 		js_ctx->h_gap = duk_known_hstring(thr, -1);
37290 	} else {
37291 		/* nop */
37292 	}
37293 
37294 	if (js_ctx->h_gap != NULL) {
37295 		/* If gap is empty, behave as if not given at all.  Check
37296 		 * against byte length because character length is more
37297 		 * expensive.
37298 		 */
37299 		if (DUK_HSTRING_GET_BYTELEN(js_ctx->h_gap) == 0) {
37300 			js_ctx->h_gap = NULL;
37301 		}
37302 	}
37303 
37304 	/* [ ... buf loop (proplist) (gap) ] */
37305 
37306 	/*
37307 	 *  Fast path: assume no mutation, iterate object property tables
37308 	 *  directly; bail out if that assumption doesn't hold.
37309 	 */
37310 
37311 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37312 	if (js_ctx->h_replacer == NULL &&  /* replacer is a mutation risk */
37313 	    js_ctx->idx_proplist == -1) {  /* proplist is very rare */
37314 		duk_int_t pcall_rc;
37315 		duk_small_uint_t prev_ms_base_flags;
37316 
37317 		DUK_DD(DUK_DDPRINT("try JSON.stringify() fast path"));
37318 
37319 		/* Use recursion_limit to ensure we don't overwrite js_ctx->visiting[]
37320 		 * array so we don't need two counter checks in the fast path.  The
37321 		 * slow path has a much larger recursion limit which we'll use if
37322 		 * necessary.
37323 		 */
37324 		DUK_ASSERT(DUK_USE_JSON_ENC_RECLIMIT >= DUK_JSON_ENC_LOOPARRAY);
37325 		js_ctx->recursion_limit = DUK_JSON_ENC_LOOPARRAY;
37326 		DUK_ASSERT(js_ctx->recursion_depth == 0);
37327 
37328 		/* Execute the fast path in a protected call.  If any error is thrown,
37329 		 * fall back to the slow path.  This includes e.g. recursion limit
37330 		 * because the fast path has a smaller recursion limit (and simpler,
37331 		 * limited loop detection).
37332 		 */
37333 
37334 		duk_dup(thr, idx_value);
37335 
37336 		/* Must prevent finalizers which may have arbitrary side effects. */
37337 		prev_ms_base_flags = thr->heap->ms_base_flags;
37338 		thr->heap->ms_base_flags |=
37339 		        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact any objects. */
37340 		thr->heap->pf_prevent_count++;                 /* Prevent finalizers. */
37341 		DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
37342 
37343 		pcall_rc = duk_safe_call(thr, duk__json_stringify_fast, (void *) js_ctx /*udata*/, 1 /*nargs*/, 0 /*nret*/);
37344 
37345 		DUK_ASSERT(thr->heap->pf_prevent_count > 0);
37346 		thr->heap->pf_prevent_count--;
37347 		thr->heap->ms_base_flags = prev_ms_base_flags;
37348 
37349 		if (pcall_rc == DUK_EXEC_SUCCESS) {
37350 			DUK_DD(DUK_DDPRINT("fast path successful"));
37351 			DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37352 			goto replace_finished;
37353 		}
37354 
37355 		/* We come here for actual aborts (like encountering .toJSON())
37356 		 * but also for recursion/loop errors.  Bufwriter size can be
37357 		 * kept because we'll probably need at least as much as we've
37358 		 * allocated so far.
37359 		 */
37360 		DUK_D(DUK_DPRINT("fast path failed, serialize using slow path instead"));
37361 		DUK_BW_RESET_SIZE(thr, &js_ctx->bw);
37362 		js_ctx->recursion_depth = 0;
37363 	}
37364 #endif
37365 
37366 	/*
37367 	 *  Create wrapper object and serialize
37368 	 */
37369 
37370 	idx_holder = duk_push_object(thr);
37371 	duk_dup(thr, idx_value);
37372 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_EMPTY_STRING);
37373 
37374 	DUK_DDD(DUK_DDDPRINT("before: flags=0x%08lx, loop=%!T, replacer=%!O, "
37375 	                     "proplist=%!T, gap=%!O, holder=%!T",
37376 	                     (unsigned long) js_ctx->flags,
37377 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37378 	                     (duk_heaphdr *) js_ctx->h_replacer,
37379 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37380 	                     (duk_heaphdr *) js_ctx->h_gap,
37381 	                     (duk_tval *) duk_get_tval(thr, -1)));
37382 
37383 	/* serialize the wrapper with empty string key */
37384 
37385 	duk_push_hstring_empty(thr);
37386 
37387 	/* [ ... buf loop (proplist) (gap) holder "" ] */
37388 
37389 	js_ctx->recursion_limit = DUK_USE_JSON_ENC_RECLIMIT;
37390 	DUK_ASSERT(js_ctx->recursion_depth == 0);
37391 
37392 	if (DUK_UNLIKELY(duk__enc_value(js_ctx, idx_holder) == 0)) {  /* [ ... holder key ] -> [ ... holder ] */
37393 		/* Result is undefined. */
37394 		duk_push_undefined(thr);
37395 	} else {
37396 		/* Convert buffer to result string. */
37397 		DUK_BW_PUSH_AS_STRING(thr, &js_ctx->bw);
37398 	}
37399 
37400 	DUK_DDD(DUK_DDDPRINT("after: flags=0x%08lx, loop=%!T, replacer=%!O, "
37401 	                     "proplist=%!T, gap=%!O, holder=%!T",
37402 	                     (unsigned long) js_ctx->flags,
37403 	                     (duk_tval *) duk_get_tval(thr, js_ctx->idx_loop),
37404 	                     (duk_heaphdr *) js_ctx->h_replacer,
37405 	                     (duk_tval *) (js_ctx->idx_proplist >= 0 ? duk_get_tval(thr, js_ctx->idx_proplist) : NULL),
37406 	                     (duk_heaphdr *) js_ctx->h_gap,
37407 	                     (duk_tval *) duk_get_tval(thr, idx_holder)));
37408 
37409 	/* The stack has a variable shape here, so force it to the
37410 	 * desired one explicitly.
37411 	 */
37412 
37413 #if defined(DUK_USE_JSON_STRINGIFY_FASTPATH)
37414  replace_finished:
37415 #endif
37416 	duk_replace(thr, entry_top);
37417 	duk_set_top(thr, entry_top + 1);
37418 
37419 	DUK_DDD(DUK_DDDPRINT("JSON stringify end: value=%!T, replacer=%!T, space=%!T, "
37420 	                     "flags=0x%08lx, result=%!T, stack_top=%ld",
37421 	                     (duk_tval *) duk_get_tval(thr, idx_value),
37422 	                     (duk_tval *) duk_get_tval(thr, idx_replacer),
37423 	                     (duk_tval *) duk_get_tval(thr, idx_space),
37424 	                     (unsigned long) flags,
37425 	                     (duk_tval *) duk_get_tval(thr, -1),
37426 	                     (long) duk_get_top(thr)));
37427 
37428 	DUK_ASSERT(duk_get_top(thr) == entry_top + 1);
37429 }
37430 
37431 #if defined(DUK_USE_JSON_BUILTIN)
37432 
37433 /*
37434  *  Entry points
37435  */
37436 
37437 DUK_INTERNAL duk_ret_t duk_bi_json_object_parse(duk_hthread *thr) {
37438 	duk_bi_json_parse_helper(thr,
37439 	                         0 /*idx_value*/,
37440 	                         1 /*idx_replacer*/,
37441 	                         0 /*flags*/);
37442 	return 1;
37443 }
37444 
37445 DUK_INTERNAL duk_ret_t duk_bi_json_object_stringify(duk_hthread *thr) {
37446 	duk_bi_json_stringify_helper(thr,
37447 	                             0 /*idx_value*/,
37448 	                             1 /*idx_replacer*/,
37449 	                             2 /*idx_space*/,
37450 	                             0 /*flags*/);
37451 	return 1;
37452 }
37453 
37454 #endif  /* DUK_USE_JSON_BUILTIN */
37455 
37456 #endif  /* DUK_USE_JSON_SUPPORT */
37457 
37458 /* automatic undefs */
37459 #undef DUK__EMIT_1
37460 #undef DUK__EMIT_2
37461 #undef DUK__EMIT_CSTR
37462 #undef DUK__EMIT_HSTR
37463 #undef DUK__EMIT_STRIDX
37464 #undef DUK__JSON_DECSTR_BUFSIZE
37465 #undef DUK__JSON_DECSTR_CHUNKSIZE
37466 #undef DUK__JSON_ENCSTR_CHUNKSIZE
37467 #undef DUK__JSON_MAX_ESC_LEN
37468 #undef DUK__JSON_STRINGIFY_BUFSIZE
37469 #undef DUK__MKESC
37470 #undef DUK__UNEMIT_1
37471 #line 1 "duk_bi_math.c"
37472 /*
37473  *  Math built-ins
37474  */
37475 
37476 /* #include duk_internal.h -> already included */
37477 
37478 #if defined(DUK_USE_MATH_BUILTIN)
37479 
37480 /*
37481  *  Use static helpers which can work with math.h functions matching
37482  *  the following signatures. This is not portable if any of these math
37483  *  functions is actually a macro.
37484  *
37485  *  Typing here is intentionally 'double' wherever values interact with
37486  *  the standard library APIs.
37487  */
37488 
37489 typedef double (*duk__one_arg_func)(double);
37490 typedef double (*duk__two_arg_func)(double, double);
37491 
37492 DUK_LOCAL duk_ret_t duk__math_minmax(duk_hthread *thr, duk_double_t initial, duk__two_arg_func min_max) {
37493 	duk_idx_t n = duk_get_top(thr);
37494 	duk_idx_t i;
37495 	duk_double_t res = initial;
37496 	duk_double_t t;
37497 
37498 	/*
37499 	 *  Note: fmax() does not match the E5 semantics.  E5 requires
37500 	 *  that if -any- input to Math.max() is a NaN, the result is a
37501 	 *  NaN.  fmax() will return a NaN only if -both- inputs are NaN.
37502 	 *  Same applies to fmin().
37503 	 *
37504 	 *  Note: every input value must be coerced with ToNumber(), even
37505 	 *  if we know the result will be a NaN anyway: ToNumber() may have
37506 	 *  side effects for which even order of evaluation matters.
37507 	 */
37508 
37509 	for (i = 0; i < n; i++) {
37510 		t = duk_to_number(thr, i);
37511 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN || DUK_FPCLASSIFY(res) == DUK_FP_NAN) {
37512 			/* Note: not normalized, but duk_push_number() will normalize */
37513 			res = (duk_double_t) DUK_DOUBLE_NAN;
37514 		} else {
37515 			res = (duk_double_t) min_max(res, (double) t);
37516 		}
37517 	}
37518 
37519 	duk_push_number(thr, res);
37520 	return 1;
37521 }
37522 
37523 DUK_LOCAL double duk__fmin_fixed(double x, double y) {
37524 	/* fmin() with args -0 and +0 is not guaranteed to return
37525 	 * -0 as ECMAScript requires.
37526 	 */
37527 	if (x == 0 && y == 0) {
37528 		duk_double_union du1, du2;
37529 		du1.d = x;
37530 		du2.d = y;
37531 
37532 		/* Already checked to be zero so these must hold, and allow us
37533 		 * to check for "x is -0 or y is -0" by ORing the high parts
37534 		 * for comparison.
37535 		 */
37536 		DUK_ASSERT(du1.ui[DUK_DBL_IDX_UI0] == 0 || du1.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37537 		DUK_ASSERT(du2.ui[DUK_DBL_IDX_UI0] == 0 || du2.ui[DUK_DBL_IDX_UI0] == 0x80000000UL);
37538 
37539 		/* XXX: what's the safest way of creating a negative zero? */
37540 		if ((du1.ui[DUK_DBL_IDX_UI0] | du2.ui[DUK_DBL_IDX_UI0]) != 0) {
37541 			/* Enter here if either x or y (or both) is -0. */
37542 			return -0.0;
37543 		} else {
37544 			return +0.0;
37545 		}
37546 	}
37547 	return duk_double_fmin(x, y);
37548 }
37549 
37550 DUK_LOCAL double duk__fmax_fixed(double x, double y) {
37551 	/* fmax() with args -0 and +0 is not guaranteed to return
37552 	 * +0 as ECMAScript requires.
37553 	 */
37554 	if (x == 0 && y == 0) {
37555 		if (DUK_SIGNBIT(x) == 0 || DUK_SIGNBIT(y) == 0) {
37556 			return +0.0;
37557 		} else {
37558 			return -0.0;
37559 		}
37560 	}
37561 	return duk_double_fmax(x, y);
37562 }
37563 
37564 #if defined(DUK_USE_ES6)
37565 DUK_LOCAL double duk__cbrt(double x) {
37566 	/* cbrt() is C99.  To avoid hassling embedders with the need to provide a
37567 	 * cube root function, we can get by with pow().  The result is not
37568 	 * identical, but that's OK: ES2015 says it's implementation-dependent.
37569 	 */
37570 
37571 #if defined(DUK_CBRT)
37572 	/* cbrt() matches ES2015 requirements. */
37573 	return DUK_CBRT(x);
37574 #else
37575 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37576 
37577 	/* pow() does not, however. */
37578 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37579 		return x;
37580 	}
37581 	if (DUK_SIGNBIT(x)) {
37582 		return -DUK_POW(-x, 1.0 / 3.0);
37583 	} else {
37584 		return DUK_POW(x, 1.0 / 3.0);
37585 	}
37586 #endif
37587 }
37588 
37589 DUK_LOCAL double duk__log2(double x) {
37590 #if defined(DUK_LOG2)
37591 	return DUK_LOG2(x);
37592 #else
37593 	return DUK_LOG(x) * DUK_DOUBLE_LOG2E;
37594 #endif
37595 }
37596 
37597 DUK_LOCAL double duk__log10(double x) {
37598 #if defined(DUK_LOG10)
37599 	return DUK_LOG10(x);
37600 #else
37601 	return DUK_LOG(x) * DUK_DOUBLE_LOG10E;
37602 #endif
37603 }
37604 
37605 DUK_LOCAL double duk__trunc(double x) {
37606 #if defined(DUK_TRUNC)
37607 	return DUK_TRUNC(x);
37608 #else
37609 	/* Handles -0 correctly: -0.0 matches 'x >= 0.0' but floor()
37610 	 * is required to return -0 when the argument is -0.
37611 	 */
37612 	return x >= 0.0 ? DUK_FLOOR(x) : DUK_CEIL(x);
37613 #endif
37614 }
37615 #endif  /* DUK_USE_ES6 */
37616 
37617 DUK_LOCAL double duk__round_fixed(double x) {
37618 	/* Numbers half-way between integers must be rounded towards +Infinity,
37619 	 * e.g. -3.5 must be rounded to -3 (not -4).  When rounded to zero, zero
37620 	 * sign must be set appropriately.  E5.1 Section 15.8.2.15.
37621 	 *
37622 	 * Note that ANSI C round() is "round to nearest integer, away from zero",
37623 	 * which is incorrect for negative values.  Here we make do with floor().
37624 	 */
37625 
37626 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
37627 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE || c == DUK_FP_ZERO) {
37628 		return x;
37629 	}
37630 
37631 	/*
37632 	 *  x is finite and non-zero
37633 	 *
37634 	 *  -1.6 -> floor(-1.1) -> -2
37635 	 *  -1.5 -> floor(-1.0) -> -1  (towards +Inf)
37636 	 *  -1.4 -> floor(-0.9) -> -1
37637 	 *  -0.5 -> -0.0               (special case)
37638 	 *  -0.1 -> -0.0               (special case)
37639 	 *  +0.1 -> +0.0               (special case)
37640 	 *  +0.5 -> floor(+1.0) -> 1   (towards +Inf)
37641 	 *  +1.4 -> floor(+1.9) -> 1
37642 	 *  +1.5 -> floor(+2.0) -> 2   (towards +Inf)
37643 	 *  +1.6 -> floor(+2.1) -> 2
37644 	 */
37645 
37646 	if (x >= -0.5 && x < 0.5) {
37647 		/* +0.5 is handled by floor, this is on purpose */
37648 		if (x < 0.0) {
37649 			return -0.0;
37650 		} else {
37651 			return +0.0;
37652 		}
37653 	}
37654 
37655 	return DUK_FLOOR(x + 0.5);
37656 }
37657 
37658 /* Wrappers for calling standard math library methods.  These may be required
37659  * on platforms where one or more of the math built-ins are defined as macros
37660  * or inline functions and are thus not suitable to be used as function pointers.
37661  */
37662 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37663 DUK_LOCAL double duk__fabs(double x) {
37664 	return DUK_FABS(x);
37665 }
37666 DUK_LOCAL double duk__acos(double x) {
37667 	return DUK_ACOS(x);
37668 }
37669 DUK_LOCAL double duk__asin(double x) {
37670 	return DUK_ASIN(x);
37671 }
37672 DUK_LOCAL double duk__atan(double x) {
37673 	return DUK_ATAN(x);
37674 }
37675 DUK_LOCAL double duk__ceil(double x) {
37676 	return DUK_CEIL(x);
37677 }
37678 DUK_LOCAL double duk__cos(double x) {
37679 	return DUK_COS(x);
37680 }
37681 DUK_LOCAL double duk__exp(double x) {
37682 	return DUK_EXP(x);
37683 }
37684 DUK_LOCAL double duk__floor(double x) {
37685 	return DUK_FLOOR(x);
37686 }
37687 DUK_LOCAL double duk__log(double x) {
37688 	return DUK_LOG(x);
37689 }
37690 DUK_LOCAL double duk__sin(double x) {
37691 	return DUK_SIN(x);
37692 }
37693 DUK_LOCAL double duk__sqrt(double x) {
37694 	return DUK_SQRT(x);
37695 }
37696 DUK_LOCAL double duk__tan(double x) {
37697 	return DUK_TAN(x);
37698 }
37699 DUK_LOCAL double duk__atan2_fixed(double x, double y) {
37700 #if defined(DUK_USE_ATAN2_WORKAROUNDS)
37701 	/* Specific fixes to common atan2() implementation issues:
37702 	 * - test-bug-mingw-math-issues.js
37703 	 */
37704 	if (DUK_ISINF(x) && DUK_ISINF(y)) {
37705 		if (DUK_SIGNBIT(x)) {
37706 			if (DUK_SIGNBIT(y)) {
37707 				return -2.356194490192345;
37708 			} else {
37709 				return -0.7853981633974483;
37710 			}
37711 		} else {
37712 			if (DUK_SIGNBIT(y)) {
37713 				return 2.356194490192345;
37714 			} else {
37715 				return 0.7853981633974483;
37716 			}
37717 		}
37718 	}
37719 #else
37720 	/* Some ISO C assumptions. */
37721 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == 0.7853981633974483);
37722 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY) == -0.7853981633974483);
37723 	DUK_ASSERT(DUK_ATAN2(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == 2.356194490192345);
37724 	DUK_ASSERT(DUK_ATAN2(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY) == -2.356194490192345);
37725 #endif
37726 
37727 	return DUK_ATAN2(x, y);
37728 }
37729 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37730 
37731 /* order must match constants in genbuiltins.py */
37732 DUK_LOCAL const duk__one_arg_func duk__one_arg_funcs[] = {
37733 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37734 	duk__fabs,
37735 	duk__acos,
37736 	duk__asin,
37737 	duk__atan,
37738 	duk__ceil,
37739 	duk__cos,
37740 	duk__exp,
37741 	duk__floor,
37742 	duk__log,
37743 	duk__round_fixed,
37744 	duk__sin,
37745 	duk__sqrt,
37746 	duk__tan,
37747 #if defined(DUK_USE_ES6)
37748 	duk__cbrt,
37749 	duk__log2,
37750 	duk__log10,
37751 	duk__trunc
37752 #endif
37753 #else  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37754 	DUK_FABS,
37755 	DUK_ACOS,
37756 	DUK_ASIN,
37757 	DUK_ATAN,
37758 	DUK_CEIL,
37759 	DUK_COS,
37760 	DUK_EXP,
37761 	DUK_FLOOR,
37762 	DUK_LOG,
37763 	duk__round_fixed,
37764 	DUK_SIN,
37765 	DUK_SQRT,
37766 	DUK_TAN,
37767 #if defined(DUK_USE_ES6)
37768 	duk__cbrt,
37769 	duk__log2,
37770 	duk__log10,
37771 	duk__trunc
37772 #endif
37773 #endif  /* DUK_USE_AVOID_PLATFORM_FUNCPTRS */
37774 };
37775 
37776 /* order must match constants in genbuiltins.py */
37777 DUK_LOCAL const duk__two_arg_func duk__two_arg_funcs[] = {
37778 #if defined(DUK_USE_AVOID_PLATFORM_FUNCPTRS)
37779 	duk__atan2_fixed,
37780 	duk_js_arith_pow
37781 #else
37782 	duk__atan2_fixed,
37783 	duk_js_arith_pow
37784 #endif
37785 };
37786 
37787 DUK_INTERNAL duk_ret_t duk_bi_math_object_onearg_shared(duk_hthread *thr) {
37788 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37789 	duk__one_arg_func fun;
37790 	duk_double_t arg1;
37791 
37792 	DUK_ASSERT(fun_idx >= 0);
37793 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__one_arg_funcs) / sizeof(duk__one_arg_func)));
37794 	arg1 = duk_to_number(thr, 0);
37795 	fun = duk__one_arg_funcs[fun_idx];
37796 	duk_push_number(thr, (duk_double_t) fun((double) arg1));
37797 	return 1;
37798 }
37799 
37800 DUK_INTERNAL duk_ret_t duk_bi_math_object_twoarg_shared(duk_hthread *thr) {
37801 	duk_small_int_t fun_idx = duk_get_current_magic(thr);
37802 	duk__two_arg_func fun;
37803 	duk_double_t arg1;
37804 	duk_double_t arg2;
37805 
37806 	DUK_ASSERT(fun_idx >= 0);
37807 	DUK_ASSERT(fun_idx < (duk_small_int_t) (sizeof(duk__two_arg_funcs) / sizeof(duk__two_arg_func)));
37808 	arg1 = duk_to_number(thr, 0);  /* explicit ordered evaluation to match coercion semantics */
37809 	arg2 = duk_to_number(thr, 1);
37810 	fun = duk__two_arg_funcs[fun_idx];
37811 	duk_push_number(thr, (duk_double_t) fun((double) arg1, (double) arg2));
37812 	return 1;
37813 }
37814 
37815 DUK_INTERNAL duk_ret_t duk_bi_math_object_max(duk_hthread *thr) {
37816 	return duk__math_minmax(thr, -DUK_DOUBLE_INFINITY, duk__fmax_fixed);
37817 }
37818 
37819 DUK_INTERNAL duk_ret_t duk_bi_math_object_min(duk_hthread *thr) {
37820 	return duk__math_minmax(thr, DUK_DOUBLE_INFINITY, duk__fmin_fixed);
37821 }
37822 
37823 DUK_INTERNAL duk_ret_t duk_bi_math_object_random(duk_hthread *thr) {
37824 	duk_push_number(thr, (duk_double_t) DUK_UTIL_GET_RANDOM_DOUBLE(thr));
37825 	return 1;
37826 }
37827 
37828 #if defined(DUK_USE_ES6)
37829 DUK_INTERNAL duk_ret_t duk_bi_math_object_hypot(duk_hthread *thr) {
37830 	/*
37831 	 *  E6 Section 20.2.2.18: Math.hypot
37832 	 *
37833 	 *  - If no arguments are passed, the result is +0.
37834 	 *  - If any argument is +inf, the result is +inf.
37835 	 *  - If any argument is -inf, the result is +inf.
37836 	 *  - If no argument is +inf or -inf, and any argument is NaN, the result is
37837 	 *    NaN.
37838 	 *  - If all arguments are either +0 or -0, the result is +0.
37839 	 */
37840 
37841 	duk_idx_t nargs;
37842 	duk_idx_t i;
37843 	duk_bool_t found_nan;
37844 	duk_double_t max;
37845 	duk_double_t sum, summand;
37846 	duk_double_t comp, prelim;
37847 	duk_double_t t;
37848 
37849 	nargs = duk_get_top(thr);
37850 
37851 	/* Find the highest value.  Also ToNumber() coerces. */
37852 	max = 0.0;
37853 	found_nan = 0;
37854 	for (i = 0; i < nargs; i++) {
37855 		t = DUK_FABS(duk_to_number(thr, i));
37856 		if (DUK_FPCLASSIFY(t) == DUK_FP_NAN) {
37857 			found_nan = 1;
37858 		} else {
37859 			max = duk_double_fmax(max, t);
37860 		}
37861 	}
37862 
37863 	/* Early return cases. */
37864 	if (max == DUK_DOUBLE_INFINITY) {
37865 		duk_push_number(thr, DUK_DOUBLE_INFINITY);
37866 		return 1;
37867 	} else if (found_nan) {
37868 		duk_push_number(thr, DUK_DOUBLE_NAN);
37869 		return 1;
37870 	} else if (max == 0.0) {
37871 		duk_push_number(thr, 0.0);
37872 		/* Otherwise we'd divide by zero. */
37873 		return 1;
37874 	}
37875 
37876 	/* Use Kahan summation and normalize to the highest value to minimize
37877 	 * floating point rounding error and avoid overflow.
37878 	 *
37879 	 * https://en.wikipedia.org/wiki/Kahan_summation_algorithm
37880 	 */
37881 	sum = 0.0;
37882 	comp = 0.0;
37883 	for (i = 0; i < nargs; i++) {
37884 		t = DUK_FABS(duk_get_number(thr, i)) / max;
37885 		summand = (t * t) - comp;
37886 		prelim = sum + summand;
37887 		comp = (prelim - sum) - summand;
37888 		sum = prelim;
37889 	}
37890 
37891 	duk_push_number(thr, (duk_double_t) DUK_SQRT(sum) * max);
37892 	return 1;
37893 }
37894 #endif  /* DUK_USE_ES6 */
37895 
37896 #if defined(DUK_USE_ES6)
37897 DUK_INTERNAL duk_ret_t duk_bi_math_object_sign(duk_hthread *thr) {
37898 	duk_double_t d;
37899 
37900 	d = duk_to_number(thr, 0);
37901 	if (duk_double_is_nan(d)) {
37902 		DUK_ASSERT(duk_is_nan(thr, -1));
37903 		return 1;  /* NaN input -> return NaN */
37904 	}
37905 	if (d == 0.0) {
37906 		/* Zero sign kept, i.e. -0 -> -0, +0 -> +0. */
37907 		return 1;
37908 	}
37909 	duk_push_int(thr, (d > 0.0 ? 1 : -1));
37910 	return 1;
37911 }
37912 #endif  /* DUK_USE_ES6 */
37913 
37914 #if defined(DUK_USE_ES6)
37915 DUK_INTERNAL duk_ret_t duk_bi_math_object_clz32(duk_hthread *thr) {
37916 	duk_uint32_t x;
37917 	duk_small_uint_t i;
37918 
37919 #if defined(DUK_USE_PREFER_SIZE)
37920 	duk_uint32_t mask;
37921 
37922 	x = duk_to_uint32(thr, 0);
37923 	for (i = 0, mask = 0x80000000UL; mask != 0; mask >>= 1) {
37924 		if (x & mask) {
37925 			break;
37926 		}
37927 		i++;
37928 	}
37929 	DUK_ASSERT(i <= 32);
37930 	duk_push_uint(thr, i);
37931 	return 1;
37932 #else  /* DUK_USE_PREFER_SIZE */
37933 	i = 0;
37934 	x = duk_to_uint32(thr, 0);
37935 	if (x & 0xffff0000UL) {
37936 		x >>= 16;
37937 	} else {
37938 		i += 16;
37939 	}
37940 	if (x & 0x0000ff00UL) {
37941 		x >>= 8;
37942 	} else {
37943 		i += 8;
37944 	}
37945 	if (x & 0x000000f0UL) {
37946 		x >>= 4;
37947 	} else {
37948 		i += 4;
37949 	}
37950 	if (x & 0x0000000cUL) {
37951 		x >>= 2;
37952 	} else {
37953 		i += 2;
37954 	}
37955 	if (x & 0x00000002UL) {
37956 		x >>= 1;
37957 	} else {
37958 		i += 1;
37959 	}
37960 	if (x & 0x00000001UL) {
37961 		;
37962 	} else {
37963 		i += 1;
37964 	}
37965 	DUK_ASSERT(i <= 32);
37966 	duk_push_uint(thr, i);
37967 	return 1;
37968 #endif  /* DUK_USE_PREFER_SIZE */
37969 }
37970 #endif  /* DUK_USE_ES6 */
37971 
37972 #if defined(DUK_USE_ES6)
37973 DUK_INTERNAL duk_ret_t duk_bi_math_object_imul(duk_hthread *thr) {
37974 	duk_uint32_t x, y, z;
37975 
37976 	x = duk_to_uint32(thr, 0);
37977 	y = duk_to_uint32(thr, 1);
37978 	z = x * y;
37979 
37980 	/* While arguments are ToUint32() coerced and the multiplication
37981 	 * is unsigned as such, the final result is curiously interpreted
37982 	 * as a signed 32-bit value.
37983 	 */
37984 	duk_push_i32(thr, (duk_int32_t) z);
37985 	return 1;
37986 }
37987 #endif  /* DUK_USE_ES6 */
37988 
37989 #endif  /* DUK_USE_MATH_BUILTIN */
37990 #line 1 "duk_bi_number.c"
37991 /*
37992  *  Number built-ins
37993  */
37994 
37995 /* #include duk_internal.h -> already included */
37996 
37997 #if defined(DUK_USE_NUMBER_BUILTIN)
37998 
37999 DUK_LOCAL duk_double_t duk__push_this_number_plain(duk_hthread *thr) {
38000 	duk_hobject *h;
38001 
38002 	/* Number built-in accepts a plain number or a Number object (whose
38003 	 * internal value is operated on).  Other types cause TypeError.
38004 	 */
38005 
38006 	duk_push_this(thr);
38007 	if (duk_is_number(thr, -1)) {
38008 		DUK_DDD(DUK_DDDPRINT("plain number value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38009 		goto done;
38010 	}
38011 	h = duk_get_hobject(thr, -1);
38012 	if (!h ||
38013 	    (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_NUMBER)) {
38014 		DUK_DDD(DUK_DDDPRINT("unacceptable this value: %!T", (duk_tval *) duk_get_tval(thr, -1)));
38015 		DUK_ERROR_TYPE(thr, "number expected");
38016 		DUK_WO_NORETURN(return 0.0;);
38017 	}
38018 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
38019 	DUK_ASSERT(duk_is_number(thr, -1));
38020 	DUK_DDD(DUK_DDDPRINT("number object: %!T, internal value: %!T",
38021 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
38022 	duk_remove_m2(thr);
38023 
38024  done:
38025 	return duk_get_number(thr, -1);
38026 }
38027 
38028 DUK_INTERNAL duk_ret_t duk_bi_number_constructor(duk_hthread *thr) {
38029 	duk_idx_t nargs;
38030 	duk_hobject *h_this;
38031 
38032 	/*
38033 	 *  The Number constructor uses ToNumber(arg) for number coercion
38034 	 *  (coercing an undefined argument to NaN).  However, if the
38035 	 *  argument is not given at all, +0 must be used instead.  To do
38036 	 *  this, a vararg function is used.
38037 	 */
38038 
38039 	nargs = duk_get_top(thr);
38040 	if (nargs == 0) {
38041 		duk_push_int(thr, 0);
38042 	}
38043 	duk_to_number(thr, 0);
38044 	duk_set_top(thr, 1);
38045 	DUK_ASSERT_TOP(thr, 1);
38046 
38047 	if (!duk_is_constructor_call(thr)) {
38048 		return 1;
38049 	}
38050 
38051 	/*
38052 	 *  E5 Section 15.7.2.1 requires that the constructed object
38053 	 *  must have the original Number.prototype as its internal
38054 	 *  prototype.  However, since Number.prototype is non-writable
38055 	 *  and non-configurable, this doesn't have to be enforced here:
38056 	 *  The default object (bound to 'this') is OK, though we have
38057 	 *  to change its class.
38058 	 *
38059 	 *  Internal value set to ToNumber(arg) or +0; if no arg given,
38060 	 *  ToNumber(undefined) = NaN, so special treatment is needed
38061 	 *  (above).  String internal value is immutable.
38062 	 */
38063 
38064 	/* XXX: helper */
38065 	duk_push_this(thr);
38066 	h_this = duk_known_hobject(thr, -1);
38067 	DUK_HOBJECT_SET_CLASS_NUMBER(h_this, DUK_HOBJECT_CLASS_NUMBER);
38068 
38069 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_this) == thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE]);
38070 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_this) == DUK_HOBJECT_CLASS_NUMBER);
38071 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_this));
38072 
38073 	duk_dup_0(thr);  /* -> [ val obj val ] */
38074 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
38075 	return 0;  /* no return value -> don't replace created value */
38076 }
38077 
38078 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_value_of(duk_hthread *thr) {
38079 	(void) duk__push_this_number_plain(thr);
38080 	return 1;
38081 }
38082 
38083 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_string(duk_hthread *thr) {
38084 	duk_small_int_t radix;
38085 	duk_small_uint_t n2s_flags;
38086 
38087 	(void) duk__push_this_number_plain(thr);
38088 	if (duk_is_undefined(thr, 0)) {
38089 		radix = 10;
38090 	} else {
38091 		radix = (duk_small_int_t) duk_to_int_check_range(thr, 0, 2, 36);
38092 	}
38093 	DUK_DDD(DUK_DDDPRINT("radix=%ld", (long) radix));
38094 
38095 	n2s_flags = 0;
38096 
38097 	duk_numconv_stringify(thr,
38098 	                      radix /*radix*/,
38099 	                      0 /*digits*/,
38100 	                      n2s_flags /*flags*/);
38101 	return 1;
38102 }
38103 
38104 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_locale_string(duk_hthread *thr) {
38105 	/* XXX: just use toString() for now; permitted although not recommended.
38106 	 * nargs==1, so radix is passed to toString().
38107 	 */
38108 	return duk_bi_number_prototype_to_string(thr);
38109 }
38110 
38111 /*
38112  *  toFixed(), toExponential(), toPrecision()
38113  */
38114 
38115 /* XXX: shared helper for toFixed(), toExponential(), toPrecision()? */
38116 
38117 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_fixed(duk_hthread *thr) {
38118 	duk_small_int_t frac_digits;
38119 	duk_double_t d;
38120 	duk_small_int_t c;
38121 	duk_small_uint_t n2s_flags;
38122 
38123 	/* In ES5.1 frac_digits is coerced first; in ES2015 the 'this number
38124 	 * value' check is done first.
38125 	 */
38126 	d = duk__push_this_number_plain(thr);
38127 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38128 
38129 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38130 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38131 		goto use_to_string;
38132 	}
38133 
38134 	if (d >= 1.0e21 || d <= -1.0e21) {
38135 		goto use_to_string;
38136 	}
38137 
38138 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38139 	            DUK_N2S_FLAG_FRACTION_DIGITS;
38140 
38141 	duk_numconv_stringify(thr,
38142 	                      10 /*radix*/,
38143 	                      frac_digits /*digits*/,
38144 	                      n2s_flags /*flags*/);
38145 	return 1;
38146 
38147  use_to_string:
38148 	DUK_ASSERT_TOP(thr, 2);
38149 	duk_to_string(thr, -1);
38150 	return 1;
38151 }
38152 
38153 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_exponential(duk_hthread *thr) {
38154 	duk_bool_t frac_undefined;
38155 	duk_small_int_t frac_digits;
38156 	duk_double_t d;
38157 	duk_small_int_t c;
38158 	duk_small_uint_t n2s_flags;
38159 
38160 	d = duk__push_this_number_plain(thr);
38161 
38162 	frac_undefined = duk_is_undefined(thr, 0);
38163 	duk_to_int(thr, 0);  /* for side effects */
38164 
38165 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38166 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38167 		goto use_to_string;
38168 	}
38169 
38170 	frac_digits = (duk_small_int_t) duk_to_int_check_range(thr, 0, 0, 20);
38171 
38172 	n2s_flags = DUK_N2S_FLAG_FORCE_EXP |
38173 	           (frac_undefined ? 0 : DUK_N2S_FLAG_FIXED_FORMAT);
38174 
38175 	duk_numconv_stringify(thr,
38176 	                      10 /*radix*/,
38177 	                      frac_digits + 1 /*leading digit + fractions*/,
38178 	                      n2s_flags /*flags*/);
38179 	return 1;
38180 
38181  use_to_string:
38182 	DUK_ASSERT_TOP(thr, 2);
38183 	duk_to_string(thr, -1);
38184 	return 1;
38185 }
38186 
38187 DUK_INTERNAL duk_ret_t duk_bi_number_prototype_to_precision(duk_hthread *thr) {
38188 	/* The specification has quite awkward order of coercion and
38189 	 * checks for toPrecision().  The operations below are a bit
38190 	 * reordered, within constraints of observable side effects.
38191 	 */
38192 
38193 	duk_double_t d;
38194 	duk_small_int_t prec;
38195 	duk_small_int_t c;
38196 	duk_small_uint_t n2s_flags;
38197 
38198 	DUK_ASSERT_TOP(thr, 1);
38199 
38200 	d = duk__push_this_number_plain(thr);
38201 	if (duk_is_undefined(thr, 0)) {
38202 		goto use_to_string;
38203 	}
38204 	DUK_ASSERT_TOP(thr, 2);
38205 
38206 	duk_to_int(thr, 0);  /* for side effects */
38207 
38208 	c = (duk_small_int_t) DUK_FPCLASSIFY(d);
38209 	if (c == DUK_FP_NAN || c == DUK_FP_INFINITE) {
38210 		goto use_to_string;
38211 	}
38212 
38213 	prec = (duk_small_int_t) duk_to_int_check_range(thr, 0, 1, 21);
38214 
38215 	n2s_flags = DUK_N2S_FLAG_FIXED_FORMAT |
38216 	            DUK_N2S_FLAG_NO_ZERO_PAD;
38217 
38218 	duk_numconv_stringify(thr,
38219 	                      10 /*radix*/,
38220 	                      prec /*digits*/,
38221 	                      n2s_flags /*flags*/);
38222 	return 1;
38223 
38224  use_to_string:
38225 	/* Used when precision is undefined; also used for NaN (-> "NaN"),
38226 	 * and +/- infinity (-> "Infinity", "-Infinity").
38227 	 */
38228 
38229 	DUK_ASSERT_TOP(thr, 2);
38230 	duk_to_string(thr, -1);
38231 	return 1;
38232 }
38233 
38234 /*
38235  *  ES2015 isFinite() etc
38236  */
38237 
38238 #if defined(DUK_USE_ES6)
38239 DUK_INTERNAL duk_ret_t duk_bi_number_check_shared(duk_hthread *thr) {
38240 	duk_int_t magic;
38241 	duk_bool_t ret = 0;
38242 
38243 	if (duk_is_number(thr, 0)) {
38244 		duk_double_t d;
38245 
38246 		magic = duk_get_current_magic(thr);
38247 		d = duk_get_number(thr, 0);
38248 
38249 		switch (magic) {
38250 		case 0:  /* isFinite() */
38251 			ret = duk_double_is_finite(d);
38252 			break;
38253 		case 1:  /* isInteger() */
38254 			ret = duk_double_is_integer(d);
38255 			break;
38256 		case 2:  /* isNaN() */
38257 			ret = duk_double_is_nan(d);
38258 			break;
38259 		default:  /* isSafeInteger() */
38260 			DUK_ASSERT(magic == 3);
38261 			ret = duk_double_is_safe_integer(d);
38262 		}
38263 	}
38264 
38265 	duk_push_boolean(thr, ret);
38266 	return 1;
38267 }
38268 #endif  /* DUK_USE_ES6 */
38269 
38270 #endif  /* DUK_USE_NUMBER_BUILTIN */
38271 #line 1 "duk_bi_object.c"
38272 /*
38273  *  Object built-ins
38274  */
38275 
38276 /* #include duk_internal.h -> already included */
38277 
38278 /* Needed even when Object built-in disabled. */
38279 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_hthread *thr) {
38280 	duk_tval *tv;
38281 
38282 	tv = DUK_HTHREAD_THIS_PTR(thr);
38283 	duk_push_class_string_tval(thr, tv, 0 /*avoid_side_effects*/);
38284 	return 1;
38285 }
38286 
38287 #if defined(DUK_USE_OBJECT_BUILTIN)
38288 DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_hthread *thr) {
38289 	duk_uint_t arg_mask;
38290 
38291 	arg_mask = duk_get_type_mask(thr, 0);
38292 
38293 	if (!duk_is_constructor_call(thr) &&  /* not a constructor call */
38294 	    ((arg_mask & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED)) == 0)) {  /* and argument not null or undefined */
38295 		duk_to_object(thr, 0);
38296 		return 1;
38297 	}
38298 
38299 	/* Pointer and buffer primitive values are treated like other
38300 	 * primitives values which have a fully fledged object counterpart:
38301 	 * promote to an object value.  Lightfuncs and plain buffers are
38302 	 * coerced with ToObject() even they could also be returned as is.
38303 	 */
38304 	if (arg_mask & (DUK_TYPE_MASK_OBJECT |
38305 	                DUK_TYPE_MASK_STRING |
38306 	                DUK_TYPE_MASK_BOOLEAN |
38307 	                DUK_TYPE_MASK_NUMBER |
38308 	                DUK_TYPE_MASK_POINTER |
38309 	                DUK_TYPE_MASK_BUFFER |
38310 	                DUK_TYPE_MASK_LIGHTFUNC)) {
38311 		/* For DUK_TYPE_OBJECT the coercion is a no-op and could
38312 		 * be checked for explicitly, but Object(obj) calls are
38313 		 * not very common so opt for minimal footprint.
38314 		 */
38315 		duk_to_object(thr, 0);
38316 		return 1;
38317 	}
38318 
38319 	(void) duk_push_object_helper(thr,
38320 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
38321 	                              DUK_HOBJECT_FLAG_FASTREFS |
38322 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38323 	                              DUK_BIDX_OBJECT_PROTOTYPE);
38324 	return 1;
38325 }
38326 #endif  /* DUK_USE_OBJECT_BUILTIN */
38327 
38328 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38329 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_hthread *thr) {
38330 	duk_idx_t nargs;
38331 	duk_int_t idx;
38332 
38333 	nargs = duk_get_top_require_min(thr, 1 /*min_top*/);
38334 
38335 	duk_to_object(thr, 0);
38336 	for (idx = 1; idx < nargs; idx++) {
38337 		/* E7 19.1.2.1 (step 4a) */
38338 		if (duk_is_null_or_undefined(thr, idx)) {
38339 			continue;
38340 		}
38341 
38342 		/* duk_enum() respects ES2015+ [[OwnPropertyKeys]] ordering, which is
38343 		 * convenient here.
38344 		 */
38345 		duk_to_object(thr, idx);
38346 		duk_enum(thr, idx, DUK_ENUM_OWN_PROPERTIES_ONLY);
38347 		while (duk_next(thr, -1, 1 /*get_value*/)) {
38348 			/* [ target ... enum key value ] */
38349 			duk_put_prop(thr, 0);
38350 			/* [ target ... enum ] */
38351 		}
38352 		/* Could pop enumerator, but unnecessary because of duk_set_top()
38353 		 * below.
38354 		 */
38355 	}
38356 
38357 	duk_set_top(thr, 1);
38358 	return 1;
38359 }
38360 #endif
38361 
38362 #if defined(DUK_USE_OBJECT_BUILTIN) && defined(DUK_USE_ES6)
38363 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_hthread *thr) {
38364 	DUK_ASSERT_TOP(thr, 2);
38365 	duk_push_boolean(thr, duk_samevalue(thr, 0, 1));
38366 	return 1;
38367 }
38368 #endif
38369 
38370 #if defined(DUK_USE_OBJECT_BUILTIN)
38371 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_hthread *thr) {
38372 	duk_hobject *proto;
38373 
38374 	DUK_ASSERT_TOP(thr, 2);
38375 
38376 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
38377 	duk_hbufobj_promote_plain(thr, 0);
38378 #endif
38379 	proto = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_NULL);
38380 	DUK_ASSERT(proto != NULL || duk_is_null(thr, 0));
38381 
38382 	(void) duk_push_object_helper_proto(thr,
38383 	                                    DUK_HOBJECT_FLAG_EXTENSIBLE |
38384 	                                    DUK_HOBJECT_FLAG_FASTREFS |
38385 	                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
38386 	                                    proto);
38387 
38388 	if (!duk_is_undefined(thr, 1)) {
38389 		/* [ O Properties obj ] */
38390 
38391 		duk_replace(thr, 0);
38392 
38393 		/* [ obj Properties ] */
38394 
38395 		/* Just call the "original" Object.defineProperties() to
38396 		 * finish up.
38397 		 */
38398 
38399 		return duk_bi_object_constructor_define_properties(thr);
38400 	}
38401 
38402 	/* [ O Properties obj ] */
38403 
38404 	return 1;
38405 }
38406 #endif  /* DUK_USE_OBJECT_BUILTIN */
38407 
38408 #if defined(DUK_USE_OBJECT_BUILTIN)
38409 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_hthread *thr) {
38410 	duk_small_uint_t pass;
38411 	duk_uint_t defprop_flags;
38412 	duk_hobject *obj;
38413 	duk_idx_t idx_value;
38414 	duk_hobject *get;
38415 	duk_hobject *set;
38416 
38417 	/* Lightfunc and plain buffer handling by ToObject() coercion. */
38418 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38419 	DUK_ASSERT(obj != NULL);
38420 
38421 	duk_to_object(thr, 1);        /* properties object */
38422 
38423 	DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
38424 	                     (duk_tval *) duk_get_tval(thr, 0),
38425 	                     (duk_tval *) duk_get_tval(thr, 1)));
38426 
38427 	/*
38428 	 *  Two pass approach to processing the property descriptors.
38429 	 *  On first pass validate and normalize all descriptors before
38430 	 *  any changes are made to the target object.  On second pass
38431 	 *  make the actual modifications to the target object.
38432 	 *
38433 	 *  Right now we'll just use the same normalize/validate helper
38434 	 *  on both passes, ignoring its outputs on the first pass.
38435 	 */
38436 
38437 	for (pass = 0; pass < 2; pass++) {
38438 		duk_set_top(thr, 2);  /* -> [ hobject props ] */
38439 		duk_enum(thr, 1, DUK_ENUM_OWN_PROPERTIES_ONLY | DUK_ENUM_INCLUDE_SYMBOLS /*enum_flags*/);
38440 
38441 		for (;;) {
38442 			duk_hstring *key;
38443 
38444 			/* [ hobject props enum(props) ] */
38445 
38446 			duk_set_top(thr, 3);
38447 
38448 			if (!duk_next(thr, 2, 1 /*get_value*/)) {
38449 				break;
38450 			}
38451 
38452 			DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
38453 			                     (duk_tval *) duk_get_tval(thr, -2),
38454 			                     (duk_tval *) duk_get_tval(thr, -1)));
38455 
38456 			/* [ hobject props enum(props) key desc ] */
38457 
38458 			duk_hobject_prepare_property_descriptor(thr,
38459 			                                        4 /*idx_desc*/,
38460 			                                        &defprop_flags,
38461 			                                        &idx_value,
38462 			                                        &get,
38463 			                                        &set);
38464 
38465 			/* [ hobject props enum(props) key desc [multiple values] ] */
38466 
38467 			if (pass == 0) {
38468 				continue;
38469 			}
38470 
38471 			/* This allows symbols on purpose. */
38472 			key = duk_known_hstring(thr, 3);
38473 			DUK_ASSERT(key != NULL);
38474 
38475 			duk_hobject_define_property_helper(thr,
38476 			                                   defprop_flags,
38477 			                                   obj,
38478 			                                   key,
38479 			                                   idx_value,
38480 			                                   get,
38481 			                                   set,
38482 			                                   1 /*throw_flag*/);
38483 		}
38484 	}
38485 
38486 	/*
38487 	 *  Return target object
38488 	 */
38489 
38490 	duk_dup_0(thr);
38491 	return 1;
38492 }
38493 #endif  /* DUK_USE_OBJECT_BUILTIN */
38494 
38495 #if defined(DUK_USE_OBJECT_BUILTIN)
38496 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_hthread *thr) {
38497 	DUK_ASSERT_TOP(thr, 1);
38498 
38499 	duk_seal_freeze_raw(thr, 0, (duk_bool_t) duk_get_current_magic(thr) /*is_freeze*/);
38500 	return 1;
38501 }
38502 #endif  /* DUK_USE_OBJECT_BUILTIN */
38503 
38504 #if defined(DUK_USE_OBJECT_BUILTIN)
38505 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_hthread *thr) {
38506 	duk_hobject *h;
38507 	duk_bool_t is_frozen;
38508 	duk_uint_t mask;
38509 
38510 	is_frozen = (duk_bool_t) duk_get_current_magic(thr);
38511 	mask = duk_get_type_mask(thr, 0);
38512 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38513 		DUK_ASSERT(is_frozen == 0 || is_frozen == 1);
38514 		duk_push_boolean(thr, (mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38515 		                          1 :               /* lightfunc always frozen and sealed */
38516 		                          (is_frozen ^ 1)); /* buffer sealed but not frozen (index props writable) */
38517 	} else {
38518 		/* ES2015 Sections 19.1.2.12, 19.1.2.13: anything other than an object
38519 		 * is considered to be already sealed and frozen.
38520 		 */
38521 		h = duk_get_hobject(thr, 0);
38522 		duk_push_boolean(thr, (h == NULL) ||
38523 		                      duk_hobject_object_is_sealed_frozen_helper(thr, h, is_frozen /*is_frozen*/));
38524 	}
38525 	return 1;
38526 }
38527 #endif  /* DUK_USE_OBJECT_BUILTIN */
38528 
38529 #if defined(DUK_USE_OBJECT_BUILTIN)
38530 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
38531 	DUK_ASSERT_TOP(thr, 0);
38532 	(void) duk_push_this_coercible_to_object(thr);
38533 	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
38534 #if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
38535 	duk_require_callable(thr, 1);
38536 #endif
38537 	duk_dup_0(thr);  /* -> [ O toString O ] */
38538 	duk_call_method(thr, 0);  /* XXX: call method tail call? */
38539 	return 1;
38540 }
38541 #endif  /* DUK_USE_OBJECT_BUILTIN */
38542 
38543 #if defined(DUK_USE_OBJECT_BUILTIN)
38544 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
38545 	/* For lightfuncs and plain buffers, returns Object() coerced. */
38546 	(void) duk_push_this_coercible_to_object(thr);
38547 	return 1;
38548 }
38549 #endif  /* DUK_USE_OBJECT_BUILTIN */
38550 
38551 #if defined(DUK_USE_OBJECT_BUILTIN)
38552 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
38553 	duk_hobject *h_v;
38554 	duk_hobject *h_obj;
38555 
38556 	DUK_ASSERT_TOP(thr, 1);
38557 
38558 	h_v = duk_get_hobject(thr, 0);
38559 	if (!h_v) {
38560 		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
38561 		return 1;
38562 	}
38563 
38564 	h_obj = duk_push_this_coercible_to_object(thr);
38565 	DUK_ASSERT(h_obj != NULL);
38566 
38567 	/* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
38568 	 * Prototype loops should cause an error to be thrown.
38569 	 */
38570 	duk_push_boolean(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
38571 	return 1;
38572 }
38573 #endif  /* DUK_USE_OBJECT_BUILTIN */
38574 
38575 #if defined(DUK_USE_OBJECT_BUILTIN)
38576 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_hthread *thr) {
38577 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, 0 /*required_desc_flags*/);
38578 }
38579 #endif  /* DUK_USE_OBJECT_BUILTIN */
38580 
38581 #if defined(DUK_USE_OBJECT_BUILTIN)
38582 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_hthread *thr) {
38583 	return (duk_ret_t) duk_hobject_object_ownprop_helper(thr, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
38584 }
38585 #endif  /* DUK_USE_OBJECT_BUILTIN */
38586 
38587 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38588 /* Shared helper to implement Object.getPrototypeOf,
38589  * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
38590  *
38591  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38592  */
38593 DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_hthread *thr) {
38594 	/*
38595 	 *  magic = 0: __proto__ getter
38596 	 *  magic = 1: Object.getPrototypeOf()
38597 	 *  magic = 2: Reflect.getPrototypeOf()
38598 	 */
38599 
38600 	duk_hobject *h;
38601 	duk_hobject *proto;
38602 	duk_tval *tv;
38603 	duk_int_t magic;
38604 
38605 	magic = duk_get_current_magic(thr);
38606 
38607 	if (magic == 0) {
38608 		DUK_ASSERT_TOP(thr, 0);
38609 		duk_push_this_coercible_to_object(thr);
38610 	}
38611 	DUK_ASSERT(duk_get_top(thr) >= 1);
38612 	if (magic < 2) {
38613 		/* ES2015 Section 19.1.2.9, step 1 */
38614 		duk_to_object(thr, 0);
38615 	}
38616 	tv = DUK_GET_TVAL_POSIDX(thr, 0);
38617 
38618 	switch (DUK_TVAL_GET_TAG(tv)) {
38619 	case DUK_TAG_BUFFER:
38620 		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38621 		break;
38622 	case DUK_TAG_LIGHTFUNC:
38623 		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
38624 		break;
38625 	case DUK_TAG_OBJECT:
38626 		h = DUK_TVAL_GET_OBJECT(tv);
38627 		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
38628 		break;
38629 	default:
38630 		/* This implicitly handles CheckObjectCoercible() caused
38631 		 * TypeError.
38632 		 */
38633 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38634 	}
38635 	if (proto != NULL) {
38636 		duk_push_hobject(thr, proto);
38637 	} else {
38638 		duk_push_null(thr);
38639 	}
38640 	return 1;
38641 }
38642 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38643 
38644 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38645 /* Shared helper to implement ES2015 Object.setPrototypeOf,
38646  * Object.prototype.__proto__ setter, and Reflect.setPrototypeOf.
38647  *
38648  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
38649  * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
38650  */
38651 DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_hthread *thr) {
38652 	/*
38653 	 *  magic = 0: __proto__ setter
38654 	 *  magic = 1: Object.setPrototypeOf()
38655 	 *  magic = 2: Reflect.setPrototypeOf()
38656 	 */
38657 
38658 	duk_hobject *h_obj;
38659 	duk_hobject *h_new_proto;
38660 	duk_hobject *h_curr;
38661 	duk_ret_t ret_success = 1;  /* retval for success path */
38662 	duk_uint_t mask;
38663 	duk_int_t magic;
38664 
38665 	/* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4). */
38666 	magic = duk_get_current_magic(thr);
38667 	if (magic == 0) {
38668 		duk_push_this_check_object_coercible(thr);
38669 		duk_insert(thr, 0);
38670 		if (!duk_check_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
38671 			return 0;
38672 		}
38673 
38674 		/* __proto__ setter returns 'undefined' on success unlike the
38675 		 * setPrototypeOf() call which returns the target object.
38676 		 */
38677 		ret_success = 0;
38678 	} else {
38679 		if (magic == 1) {
38680 			duk_require_object_coercible(thr, 0);
38681 		} else {
38682 			duk_require_hobject_accept_mask(thr, 0,
38683 			                                DUK_TYPE_MASK_LIGHTFUNC |
38684 			                                DUK_TYPE_MASK_BUFFER);
38685 		}
38686 		duk_require_type_mask(thr, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
38687 	}
38688 
38689 	h_new_proto = duk_get_hobject(thr, 1);
38690 	/* h_new_proto may be NULL */
38691 
38692 	mask = duk_get_type_mask(thr, 0);
38693 	if (mask & (DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER)) {
38694 		duk_hobject *curr_proto;
38695 		curr_proto = thr->builtins[(mask & DUK_TYPE_MASK_LIGHTFUNC) ?
38696 		                               DUK_BIDX_FUNCTION_PROTOTYPE :
38697 		                               DUK_BIDX_UINT8ARRAY_PROTOTYPE];
38698 		if (h_new_proto == curr_proto) {
38699 			goto skip;
38700 		}
38701 		goto fail_nonextensible;
38702 	}
38703 	h_obj = duk_get_hobject(thr, 0);
38704 	if (h_obj == NULL) {
38705 		goto skip;
38706 	}
38707 	DUK_ASSERT(h_obj != NULL);
38708 
38709 	/* [[SetPrototypeOf]] standard behavior, E6 9.1.2. */
38710 	/* TODO: implement Proxy object support here */
38711 
38712 	if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
38713 		goto skip;
38714 	}
38715 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
38716 		goto fail_nonextensible;
38717 	}
38718 	for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
38719 		/* Loop prevention. */
38720 		if (h_curr == h_obj) {
38721 			goto fail_loop;
38722 		}
38723 	}
38724 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
38725 	/* fall thru */
38726 
38727  skip:
38728 	duk_set_top(thr, 1);
38729 	if (magic == 2) {
38730 		duk_push_true(thr);
38731 	}
38732 	return ret_success;
38733 
38734  fail_nonextensible:
38735  fail_loop:
38736 	if (magic != 2) {
38737 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
38738 	} else {
38739 		duk_push_false(thr);
38740 		return 1;
38741 	}
38742 }
38743 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38744 
38745 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38746 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_hthread *thr) {
38747 	/*
38748 	 *  magic = 0: Object.defineProperty()
38749 	 *  magic = 1: Reflect.defineProperty()
38750 	 */
38751 
38752 	duk_hobject *obj;
38753 	duk_hstring *key;
38754 	duk_hobject *get;
38755 	duk_hobject *set;
38756 	duk_idx_t idx_value;
38757 	duk_uint_t defprop_flags;
38758 	duk_small_uint_t magic;
38759 	duk_bool_t throw_flag;
38760 	duk_bool_t ret;
38761 
38762 	DUK_ASSERT(thr != NULL);
38763 
38764 	DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
38765 	                     (void *) thr,
38766 	                     (duk_tval *) duk_get_tval(thr, 0),
38767 	                     (duk_tval *) duk_get_tval(thr, 1),
38768 	                     (duk_tval *) duk_get_tval(thr, 2)));
38769 
38770 	/* [ obj key desc ] */
38771 
38772 	magic = (duk_small_uint_t) duk_get_current_magic(thr);
38773 
38774 	/* Lightfuncs are currently supported by coercing to a temporary
38775 	 * Function object; changes will be allowed (the coerced value is
38776 	 * extensible) but will be lost.  Same for plain buffers.
38777 	 */
38778 	obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38779 	DUK_ASSERT(obj != NULL);
38780 	key = duk_to_property_key_hstring(thr, 1);
38781 	(void) duk_require_hobject(thr, 2);
38782 
38783 	DUK_ASSERT(obj != NULL);
38784 	DUK_ASSERT(key != NULL);
38785 	DUK_ASSERT(duk_get_hobject(thr, 2) != NULL);
38786 
38787 	/*
38788 	 *  Validate and convert argument property descriptor (an ECMAScript
38789 	 *  object) into a set of defprop_flags and possibly property value,
38790 	 *  getter, and/or setter values on the value stack.
38791 	 *
38792 	 *  Lightfunc set/get values are coerced to full Functions.
38793 	 */
38794 
38795 	duk_hobject_prepare_property_descriptor(thr,
38796 	                                        2 /*idx_desc*/,
38797 	                                        &defprop_flags,
38798 	                                        &idx_value,
38799 	                                        &get,
38800 	                                        &set);
38801 
38802 	/*
38803 	 *  Use Object.defineProperty() helper for the actual operation.
38804 	 */
38805 
38806 	DUK_ASSERT(magic == 0U || magic == 1U);
38807 	throw_flag = magic ^ 1U;
38808 	ret = duk_hobject_define_property_helper(thr,
38809 	                                         defprop_flags,
38810 	                                         obj,
38811 	                                         key,
38812 	                                         idx_value,
38813 	                                         get,
38814 	                                         set,
38815 	                                         throw_flag);
38816 
38817 	/* Ignore the normalize/validate helper outputs on the value stack,
38818 	 * they're popped automatically.
38819 	 */
38820 
38821 	if (magic == 0U) {
38822 		/* Object.defineProperty(): return target object. */
38823 		duk_push_hobject(thr, obj);
38824 	} else {
38825 		/* Reflect.defineProperty(): return success/fail. */
38826 		duk_push_boolean(thr, ret);
38827 	}
38828 	return 1;
38829 }
38830 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38831 
38832 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38833 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_hthread *thr) {
38834 	DUK_ASSERT_TOP(thr, 2);
38835 
38836 	/* ES2015 Section 19.1.2.6, step 1 */
38837 	if (duk_get_current_magic(thr) == 0) {
38838 		duk_to_object(thr, 0);
38839 	}
38840 
38841 	/* [ obj key ] */
38842 
38843 	duk_hobject_object_get_own_property_descriptor(thr, -2);
38844 	return 1;
38845 }
38846 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38847 
38848 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38849 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_hthread *thr) {
38850 	/*
38851 	 *  magic = 0: Object.isExtensible()
38852 	 *  magic = 1: Reflect.isExtensible()
38853 	 */
38854 
38855 	duk_hobject *h;
38856 
38857 	if (duk_get_current_magic(thr) == 0) {
38858 		h = duk_get_hobject(thr, 0);
38859 	} else {
38860 		/* Reflect.isExtensible(): throw if non-object, but we accept lightfuncs
38861 		 * and plain buffers here because they pretend to be objects.
38862 		 */
38863 		h = duk_require_hobject_accept_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38864 	}
38865 
38866 	duk_push_boolean(thr, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
38867 	return 1;
38868 }
38869 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38870 
38871 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38872 /* Shared helper for various key/symbol listings, magic:
38873  * 0=Object.keys()
38874  * 1=Object.getOwnPropertyNames(),
38875  * 2=Object.getOwnPropertySymbols(),
38876  * 3=Reflect.ownKeys()
38877  */
38878 DUK_LOCAL const duk_small_uint_t duk__object_keys_enum_flags[4] = {
38879 	/* Object.keys() */
38880 	DUK_ENUM_OWN_PROPERTIES_ONLY |
38881 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38882 
38883 	/* Object.getOwnPropertyNames() */
38884 	DUK_ENUM_INCLUDE_NONENUMERABLE |
38885 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38886 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38887 
38888 	/* Object.getOwnPropertySymbols() */
38889 	DUK_ENUM_INCLUDE_SYMBOLS |
38890 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38891 	    DUK_ENUM_EXCLUDE_STRINGS |
38892 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
38893 	    DUK_ENUM_NO_PROXY_BEHAVIOR,
38894 
38895 	/* Reflect.ownKeys() */
38896 	DUK_ENUM_INCLUDE_SYMBOLS |
38897 	    DUK_ENUM_OWN_PROPERTIES_ONLY |
38898 	    DUK_ENUM_INCLUDE_NONENUMERABLE |
38899 	    DUK_ENUM_NO_PROXY_BEHAVIOR
38900 };
38901 
38902 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_hthread *thr) {
38903 	duk_hobject *obj;
38904 #if defined(DUK_USE_ES6_PROXY)
38905 	duk_hobject *h_proxy_target;
38906 	duk_hobject *h_proxy_handler;
38907 	duk_hobject *h_trap_result;
38908 #endif
38909 	duk_small_uint_t enum_flags;
38910 	duk_int_t magic;
38911 
38912 	DUK_ASSERT_TOP(thr, 1);
38913 
38914 	magic = duk_get_current_magic(thr);
38915 	if (magic == 3) {
38916 		/* ES2015 Section 26.1.11 requires a TypeError for non-objects.  Lightfuncs
38917 		 * and plain buffers pretend to be objects, so accept those too.
38918 		 */
38919 		obj = duk_require_hobject_promote_mask(thr, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
38920 	} else {
38921 		/* ES2015: ToObject coerce. */
38922 		obj = duk_to_hobject(thr, 0);
38923 	}
38924 	DUK_ASSERT(obj != NULL);
38925 	DUK_UNREF(obj);
38926 
38927 	/* XXX: proxy chains */
38928 
38929 #if defined(DUK_USE_ES6_PROXY)
38930 	/* XXX: better sharing of code between proxy target call sites */
38931 	if (DUK_LIKELY(!duk_hobject_proxy_check(obj,
38932 	                                        &h_proxy_target,
38933 	                                        &h_proxy_handler))) {
38934 		goto skip_proxy;
38935 	}
38936 
38937 	duk_push_hobject(thr, h_proxy_handler);
38938 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
38939 		/* Careful with reachability here: don't pop 'obj' before pushing
38940 		 * proxy target.
38941 		 */
38942 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
38943 		duk_pop_2(thr);
38944 		duk_push_hobject(thr, h_proxy_target);
38945 		duk_replace(thr, 0);
38946 		DUK_ASSERT_TOP(thr, 1);
38947 		goto skip_proxy;
38948 	}
38949 
38950 	/* [ obj handler trap ] */
38951 	duk_insert(thr, -2);
38952 	duk_push_hobject(thr, h_proxy_target);  /* -> [ obj trap handler target ] */
38953 	duk_call_method(thr, 1 /*nargs*/);      /* -> [ obj trap_result ] */
38954 	h_trap_result = duk_require_hobject(thr, -1);
38955 	DUK_UNREF(h_trap_result);
38956 
38957 	magic = duk_get_current_magic(thr);
38958 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
38959 	enum_flags = duk__object_keys_enum_flags[magic];
38960 
38961 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
38962 	return 1;
38963 
38964  skip_proxy:
38965 #endif  /* DUK_USE_ES6_PROXY */
38966 
38967 	DUK_ASSERT_TOP(thr, 1);
38968 	magic = duk_get_current_magic(thr);
38969 	DUK_ASSERT(magic >= 0 && magic < (duk_int_t) (sizeof(duk__object_keys_enum_flags) / sizeof(duk_small_uint_t)));
38970 	enum_flags = duk__object_keys_enum_flags[magic];
38971 	return duk_hobject_get_enumerated_keys(thr, enum_flags);
38972 }
38973 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
38974 
38975 #if defined(DUK_USE_OBJECT_BUILTIN) || defined(DUK_USE_REFLECT_BUILTIN)
38976 DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_hthread *thr) {
38977 	/*
38978 	 *  magic = 0: Object.preventExtensions()
38979 	 *  magic = 1: Reflect.preventExtensions()
38980 	 */
38981 
38982 	duk_hobject *h;
38983 	duk_uint_t mask;
38984 	duk_int_t magic;
38985 
38986 	magic = duk_get_current_magic(thr);
38987 
38988 	/* Silent success for lightfuncs and plain buffers always. */
38989 	mask = DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER;
38990 
38991 	/* Object.preventExtensions() silent success for non-object. */
38992 	if (magic == 0) {
38993 		mask |= DUK_TYPE_MASK_UNDEFINED |
38994 		        DUK_TYPE_MASK_NULL |
38995 		        DUK_TYPE_MASK_BOOLEAN |
38996 		        DUK_TYPE_MASK_NUMBER |
38997 		        DUK_TYPE_MASK_STRING |
38998 		        DUK_TYPE_MASK_POINTER;
38999 	}
39000 
39001 	if (duk_check_type_mask(thr, 0, mask)) {
39002 		/* Not an object, already non-extensible so always success. */
39003 		goto done;
39004 	}
39005 	h = duk_require_hobject(thr, 0);
39006 	DUK_ASSERT(h != NULL);
39007 
39008 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
39009 
39010 	/* A non-extensible object cannot gain any more properties,
39011 	 * so this is a good time to compact.
39012 	 */
39013 	duk_hobject_compact_props(thr, h);
39014 
39015  done:
39016 	if (magic == 1) {
39017 		duk_push_true(thr);
39018 	}
39019 	return 1;
39020 }
39021 #endif  /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */
39022 
39023 /*
39024  *  __defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__
39025  */
39026 
39027 #if defined(DUK_USE_ES8)
39028 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_defineaccessor(duk_hthread *thr) {
39029 	duk_push_this(thr);
39030 	duk_insert(thr, 0);
39031 	duk_to_object(thr, 0);
39032 	duk_require_callable(thr, 2);
39033 
39034 	/* [ ToObject(this) key getter/setter ] */
39035 
39036 	/* ToPropertyKey() coercion is not needed, duk_def_prop() does it. */
39037 	duk_def_prop(thr, 0, DUK_DEFPROP_SET_ENUMERABLE |
39038 	                     DUK_DEFPROP_SET_CONFIGURABLE |
39039 	                     (duk_get_current_magic(thr) ? DUK_DEFPROP_HAVE_SETTER : DUK_DEFPROP_HAVE_GETTER));
39040 	return 0;
39041 }
39042 DUK_INTERNAL duk_ret_t duk_bi_object_prototype_lookupaccessor(duk_hthread *thr) {
39043 	duk_uint_t sanity;
39044 
39045 	duk_push_this(thr);
39046 	duk_to_object(thr, -1);
39047 
39048 	/* XXX: Prototype walk (with sanity) should be a core property
39049 	 * operation, could add a flag to e.g. duk_get_prop_desc().
39050 	 */
39051 
39052 	/* ToPropertyKey() coercion is not needed, duk_get_prop_desc() does it. */
39053 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
39054 	while (!duk_is_undefined(thr, -1)) {
39055 		/* [ key obj ] */
39056 		duk_dup(thr, 0);
39057 		duk_get_prop_desc(thr, 1, 0 /*flags*/);
39058 		if (!duk_is_undefined(thr, -1)) {
39059 			duk_get_prop_stridx(thr, -1, (duk_get_current_magic(thr) != 0 ? DUK_STRIDX_SET : DUK_STRIDX_GET));
39060 			return 1;
39061 		}
39062 		duk_pop(thr);
39063 
39064 		if (DUK_UNLIKELY(sanity-- == 0)) {
39065 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
39066 			DUK_WO_NORETURN(return 0;);
39067 		}
39068 
39069 		duk_get_prototype(thr, -1);
39070 		duk_remove(thr, -2);
39071 	}
39072 	return 1;
39073 }
39074 #endif  /* DUK_USE_ES8 */
39075 #line 1 "duk_bi_performance.c"
39076 /*
39077  *  High resolution time API (performance.now() et al)
39078  *
39079  *  API specification: https://encoding.spec.whatwg.org/#ap://www.w3.org/TR/hr-time/
39080  */
39081 
39082 /* #include duk_internal.h -> already included */
39083 
39084 #if defined(DUK_USE_PERFORMANCE_BUILTIN)
39085 DUK_INTERNAL duk_ret_t duk_bi_performance_now(duk_hthread *thr) {
39086 	/* From API spec:
39087 	 * The DOMHighResTimeStamp type is used to store a time value in
39088 	 * milliseconds, measured relative from the time origin, global
39089 	 * monotonic clock, or a time value that represents a duration
39090 	 * between two DOMHighResTimeStamp's.
39091 	 */
39092 	duk_push_number(thr, duk_time_get_monotonic_time(thr));
39093 	return 1;
39094 }
39095 
39096 #if 0  /* Missing until semantics decided. */
39097 DUK_INTERNAL duk_ret_t duk_bi_performance_timeorigin_getter(duk_hthread *thr) {
39098 	/* No decision yet how to handle timeOrigins, e.g. should one be
39099 	 * initialized per heap, or per global object set.  See
39100 	 * https://www.w3.org/TR/hr-time/#time-origin.
39101 	 */
39102 	duk_push_uint(thr, 0);
39103 	return 1;
39104 }
39105 #endif  /* 0 */
39106 #endif  /* DUK_USE_PERFORMANCE_BUILTIN */
39107 #line 1 "duk_bi_pointer.c"
39108 /*
39109  *  Pointer built-ins
39110  */
39111 
39112 /* #include duk_internal.h -> already included */
39113 
39114 /*
39115  *  Constructor
39116  */
39117 
39118 DUK_INTERNAL duk_ret_t duk_bi_pointer_constructor(duk_hthread *thr) {
39119 	/* XXX: this behavior is quite useless now; it would be nice to be able
39120 	 * to create pointer values from e.g. numbers or strings.  Numbers are
39121 	 * problematic on 64-bit platforms though.  Hex encoded strings?
39122 	 */
39123 	if (duk_get_top(thr) == 0) {
39124 		duk_push_pointer(thr, NULL);
39125 	} else {
39126 		duk_to_pointer(thr, 0);
39127 	}
39128 	DUK_ASSERT(duk_is_pointer(thr, 0));
39129 	duk_set_top(thr, 1);
39130 
39131 	if (duk_is_constructor_call(thr)) {
39132 		(void) duk_push_object_helper(thr,
39133 		                              DUK_HOBJECT_FLAG_EXTENSIBLE |
39134 		                              DUK_HOBJECT_FLAG_FASTREFS |
39135 		                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_POINTER),
39136 		                              DUK_BIDX_POINTER_PROTOTYPE);
39137 
39138 		/* Pointer object internal value is immutable */
39139 		duk_dup_0(thr);
39140 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39141 	}
39142 	/* Note: unbalanced stack on purpose */
39143 
39144 	return 1;
39145 }
39146 
39147 /*
39148  *  toString(), valueOf()
39149  */
39150 
39151 DUK_INTERNAL duk_ret_t duk_bi_pointer_prototype_tostring_shared(duk_hthread *thr) {
39152 	duk_tval *tv;
39153 	duk_small_int_t to_string = duk_get_current_magic(thr);
39154 
39155 	duk_push_this(thr);
39156 	tv = duk_require_tval(thr, -1);
39157 	DUK_ASSERT(tv != NULL);
39158 
39159 	if (DUK_TVAL_IS_POINTER(tv)) {
39160 		/* nop */
39161 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
39162 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
39163 		DUK_ASSERT(h != NULL);
39164 
39165 		/* Must be a "pointer object", i.e. class "Pointer" */
39166 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_POINTER) {
39167 			goto type_error;
39168 		}
39169 
39170 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
39171 	} else {
39172 		goto type_error;
39173 	}
39174 
39175 	if (to_string) {
39176 		duk_to_string(thr, -1);
39177 	}
39178 	return 1;
39179 
39180  type_error:
39181 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39182 }
39183 #line 1 "duk_bi_promise.c"
39184 /*
39185  *  Promise built-in
39186  */
39187 
39188 /* #include duk_internal.h -> already included */
39189 
39190 #if defined(DUK_USE_PROMISE_BUILTIN)
39191 
39192 DUK_INTERNAL duk_ret_t duk_bi_promise_constructor(duk_hthread *thr) {
39193 	DUK_ERROR_TYPE(thr, "unimplemented");
39194 	DUK_WO_NORETURN(return 0;);
39195 }
39196 
39197 DUK_INTERNAL duk_ret_t duk_bi_promise_all(duk_hthread *thr) {
39198 	DUK_ERROR_TYPE(thr, "unimplemented");
39199 	DUK_WO_NORETURN(return 0;);
39200 }
39201 
39202 DUK_INTERNAL duk_ret_t duk_bi_promise_race(duk_hthread *thr) {
39203 	DUK_ERROR_TYPE(thr, "unimplemented");
39204 	DUK_WO_NORETURN(return 0;);
39205 }
39206 
39207 DUK_INTERNAL duk_ret_t duk_bi_promise_reject(duk_hthread *thr) {
39208 	DUK_ERROR_TYPE(thr, "unimplemented");
39209 	DUK_WO_NORETURN(return 0;);
39210 }
39211 
39212 DUK_INTERNAL duk_ret_t duk_bi_promise_resolve(duk_hthread *thr) {
39213 	DUK_ERROR_TYPE(thr, "unimplemented");
39214 	DUK_WO_NORETURN(return 0;);
39215 }
39216 
39217 DUK_INTERNAL duk_ret_t duk_bi_promise_catch(duk_hthread *thr) {
39218 	DUK_ERROR_TYPE(thr, "unimplemented");
39219 	DUK_WO_NORETURN(return 0;);
39220 }
39221 
39222 DUK_INTERNAL duk_ret_t duk_bi_promise_then(duk_hthread *thr) {
39223 	DUK_ERROR_TYPE(thr, "unimplemented");
39224 	DUK_WO_NORETURN(return 0;);
39225 }
39226 
39227 #endif  /* DUK_USE_PROMISE_BUILTIN */
39228 #line 1 "duk_bi_proxy.c"
39229 /*
39230  *  Proxy built-in (ES2015)
39231  */
39232 
39233 /* #include duk_internal.h -> already included */
39234 
39235 #if defined(DUK_USE_ES6_PROXY)
39236 /* Post-process a Proxy ownKeys() result at stack top.  Push a cleaned up
39237  * array of valid result keys (strings or symbols).  TypeError for invalid
39238  * values.  Flags are shared with duk_enum().
39239  */
39240 DUK_INTERNAL void duk_proxy_ownkeys_postprocess(duk_hthread *thr, duk_hobject *h_proxy_target, duk_uint_t flags) {
39241 	duk_uarridx_t i, len, idx;
39242 	duk_propdesc desc;
39243 
39244 	DUK_ASSERT_CTX_VALID(thr);
39245 	DUK_ASSERT(h_proxy_target != NULL);
39246 
39247 	len = (duk_uarridx_t) duk_get_length(thr, -1);
39248 	idx = 0;
39249 	duk_push_array(thr);
39250 	/* XXX: preallocated dense array, fill in directly */
39251 	for (i = 0; i < len; i++) {
39252 		duk_hstring *h;
39253 
39254 		/* [ obj trap_result res_arr ] */
39255 		(void) duk_get_prop_index(thr, -2, i);
39256 		h = duk_get_hstring(thr, -1);
39257 		if (h == NULL) {
39258 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
39259 			DUK_WO_NORETURN(return;);
39260 		}
39261 
39262 		if (!(flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
39263 			/* No support for 'getOwnPropertyDescriptor' trap yet,
39264 			 * so check enumerability always from target object
39265 			 * descriptor.
39266 			 */
39267 			if (duk_hobject_get_own_propdesc(thr, h_proxy_target, duk_known_hstring(thr, -1), &desc, 0 /*flags*/)) {
39268 				if ((desc.flags & DUK_PROPDESC_FLAG_ENUMERABLE) == 0) {
39269 					DUK_DDD(DUK_DDDPRINT("ignore non-enumerable property: %!T", duk_get_tval(thr, -1)));
39270 					goto skip_key;
39271 				}
39272 			} else {
39273 				DUK_DDD(DUK_DDDPRINT("ignore non-existent property: %!T", duk_get_tval(thr, -1)));
39274 				goto skip_key;
39275 			}
39276 		}
39277 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
39278 			if (!(flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
39279 				DUK_DDD(DUK_DDDPRINT("ignore symbol property: %!T", duk_get_tval(thr, -1)));
39280 				goto skip_key;
39281 			}
39282 			if (DUK_HSTRING_HAS_HIDDEN(h) && !(flags & DUK_ENUM_INCLUDE_HIDDEN)) {
39283 				DUK_DDD(DUK_DDDPRINT("ignore hidden symbol property: %!T", duk_get_tval(thr, -1)));
39284 				goto skip_key;
39285 			}
39286 		} else {
39287 			if (flags & DUK_ENUM_EXCLUDE_STRINGS) {
39288 				DUK_DDD(DUK_DDDPRINT("ignore string property: %!T", duk_get_tval(thr, -1)));
39289 				goto skip_key;
39290 			}
39291 		}
39292 
39293 		/* [ obj trap_result res_arr propname ] */
39294 		duk_put_prop_index(thr, -2, idx++);
39295 		continue;
39296 
39297 	 skip_key:
39298 		duk_pop(thr);
39299 		continue;
39300 	}
39301 
39302 	/* XXX: Missing trap result validation for non-configurable target keys
39303 	 * (must be present), for non-extensible target all target keys must be
39304 	 * present and no extra keys can be present.
39305 	 * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
39306 	 */
39307 
39308 	/* XXX: The key enumerability check should trigger the "getOwnPropertyDescriptor"
39309 	 * trap which has not yet been implemented.  In the absence of such a trap,
39310 	 * the enumerability should be checked from the target object; this is
39311 	 * handled above.
39312 	 */
39313 }
39314 #endif  /* DUK_USE_ES6_PROXY */
39315 
39316 #if defined(DUK_USE_ES6_PROXY)
39317 DUK_INTERNAL duk_ret_t duk_bi_proxy_constructor(duk_hthread *thr) {
39318 	DUK_ASSERT_TOP(thr, 2);  /* [ target handler ] */
39319 
39320 	duk_require_constructor_call(thr);
39321 	duk_push_proxy(thr, 0 /*flags*/);  /* [ target handler ] -> [ proxy ] */
39322 	return 1;  /* replacement */
39323 }
39324 #endif  /* DUK_USE_ES6_PROXY */
39325 #line 1 "duk_bi_reflect.c"
39326 /*
39327  *  'Reflect' built-in (ES2016 Section 26.1)
39328  *  http://www.ecma-international.org/ecma-262/7.0/#sec-reflect-object
39329  *
39330  *  Many Reflect built-in functions are provided by shared helpers in
39331  *  duk_bi_object.c or duk_bi_function.c.
39332  */
39333 
39334 /* #include duk_internal.h -> already included */
39335 
39336 #if defined(DUK_USE_REFLECT_BUILTIN)
39337 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_delete_property(duk_hthread *thr) {
39338 	duk_tval *tv_obj;
39339 	duk_tval *tv_key;
39340 	duk_bool_t ret;
39341 
39342 	DUK_ASSERT_TOP(thr, 2);
39343 	(void) duk_require_hobject(thr, 0);
39344 	(void) duk_to_string(thr, 1);
39345 
39346 	/* [ target key ] */
39347 
39348 	DUK_ASSERT(thr != NULL);
39349 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39350 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39351 	ret = duk_hobject_delprop(thr, tv_obj, tv_key, 0 /*throw_flag*/);
39352 	duk_push_boolean(thr, ret);
39353 	return 1;
39354 }
39355 
39356 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_hthread *thr) {
39357 	duk_tval *tv_obj;
39358 	duk_tval *tv_key;
39359 	duk_idx_t nargs;
39360 
39361 	DUK_ASSERT(thr != NULL);
39362 	nargs = duk_get_top_require_min(thr, 2 /*min_top*/);
39363 	(void) duk_require_hobject(thr, 0);
39364 	(void) duk_to_string(thr, 1);
39365 	if (nargs >= 3 && !duk_strict_equals(thr, 0, 2)) {
39366 		/* XXX: [[Get]] receiver currently unsupported */
39367 		DUK_ERROR_UNSUPPORTED(thr);
39368 		DUK_WO_NORETURN(return 0;);
39369 	}
39370 
39371 	/* [ target key receiver? ...? ] */
39372 
39373 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39374 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39375 	(void) duk_hobject_getprop(thr, tv_obj, tv_key);  /* This could also be a duk_get_prop(). */
39376 	return 1;
39377 }
39378 
39379 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_has(duk_hthread *thr) {
39380 	duk_tval *tv_obj;
39381 	duk_tval *tv_key;
39382 	duk_bool_t ret;
39383 
39384 	DUK_ASSERT(thr != NULL);
39385 	DUK_ASSERT_TOP(thr, 2);
39386 	(void) duk_require_hobject(thr, 0);
39387 	(void) duk_to_string(thr, 1);
39388 
39389 	/* [ target key ] */
39390 
39391 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39392 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39393 	ret = duk_hobject_hasprop(thr, tv_obj, tv_key);
39394 	duk_push_boolean(thr, ret);
39395 	return 1;
39396 }
39397 
39398 DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_hthread *thr) {
39399 	duk_tval *tv_obj;
39400 	duk_tval *tv_key;
39401 	duk_tval *tv_val;
39402 	duk_idx_t nargs;
39403 	duk_bool_t ret;
39404 
39405 	DUK_ASSERT(thr != NULL);
39406 	nargs = duk_get_top_require_min(thr, 3 /*min_top*/);
39407 	(void) duk_require_hobject(thr, 0);
39408 	(void) duk_to_string(thr, 1);
39409 	if (nargs >= 4 && !duk_strict_equals(thr, 0, 3)) {
39410 		/* XXX: [[Set]] receiver currently unsupported */
39411 		DUK_ERROR_UNSUPPORTED(thr);
39412 		DUK_WO_NORETURN(return 0;);
39413 	}
39414 
39415 	/* [ target key value receiver? ...? ] */
39416 
39417 	tv_obj = DUK_GET_TVAL_POSIDX(thr, 0);
39418 	tv_key = DUK_GET_TVAL_POSIDX(thr, 1);
39419 	tv_val = DUK_GET_TVAL_POSIDX(thr, 2);
39420 	ret = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, 0 /*throw_flag*/);
39421 	duk_push_boolean(thr, ret);
39422 	return 1;
39423 }
39424 #endif  /* DUK_USE_REFLECT_BUILTIN */
39425 #line 1 "duk_bi_regexp.c"
39426 /*
39427  *  RegExp built-ins
39428  */
39429 
39430 /* #include duk_internal.h -> already included */
39431 
39432 #if defined(DUK_USE_REGEXP_SUPPORT)
39433 
39434 DUK_LOCAL void duk__get_this_regexp(duk_hthread *thr) {
39435 	duk_hobject *h;
39436 
39437 	duk_push_this(thr);
39438 	h = duk_require_hobject_with_class(thr, -1, DUK_HOBJECT_CLASS_REGEXP);
39439 	DUK_ASSERT(h != NULL);
39440 	DUK_UNREF(h);
39441 	duk_insert(thr, 0);  /* prepend regexp to valstack 0 index */
39442 }
39443 
39444 /* XXX: much to improve (code size) */
39445 DUK_INTERNAL duk_ret_t duk_bi_regexp_constructor(duk_hthread *thr) {
39446 	duk_hobject *h_pattern;
39447 
39448 	DUK_ASSERT_TOP(thr, 2);
39449 	h_pattern = duk_get_hobject(thr, 0);
39450 
39451 	if (!duk_is_constructor_call(thr) &&
39452 	    h_pattern != NULL &&
39453 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP &&
39454 	    duk_is_undefined(thr, 1)) {
39455 		/* Called as a function, pattern has [[Class]] "RegExp" and
39456 		 * flags is undefined -> return object as is.
39457 		 */
39458 		/* XXX: ES2015 has a NewTarget SameValue() check which is not
39459 		 * yet implemented.
39460 		 */
39461 		duk_dup_0(thr);
39462 		return 1;
39463 	}
39464 
39465 	/* Else functionality is identical for function call and constructor
39466 	 * call.
39467 	 */
39468 
39469 	if (h_pattern != NULL &&
39470 	    DUK_HOBJECT_GET_CLASS_NUMBER(h_pattern) == DUK_HOBJECT_CLASS_REGEXP) {
39471 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_SOURCE);
39472 		if (duk_is_undefined(thr, 1)) {
39473 			/* In ES5 one would need to read the flags individually;
39474 			 * in ES2015 just read .flags.
39475 			 */
39476 			duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39477 		} else {
39478 			/* In ES2015 allowed; overrides argument RegExp flags. */
39479 			duk_dup_1(thr);
39480 		}
39481 	} else {
39482 		if (duk_is_undefined(thr, 0)) {
39483 			duk_push_hstring_empty(thr);
39484 		} else {
39485 			duk_dup_0(thr);
39486 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39487 		}
39488 		if (duk_is_undefined(thr, 1)) {
39489 			duk_push_hstring_empty(thr);
39490 		} else {
39491 			duk_dup_1(thr);
39492 			duk_to_string(thr, -1);  /* Rejects Symbols. */
39493 		}
39494 
39495 		/* [ ... pattern flags ] */
39496 	}
39497 
39498 	DUK_DDD(DUK_DDDPRINT("RegExp constructor/function call, pattern=%!T, flags=%!T",
39499 	                     (duk_tval *) duk_get_tval(thr, -2), (duk_tval *) duk_get_tval(thr, -1)));
39500 
39501 	/* [ ... pattern flags ] (both uncoerced) */
39502 
39503 	duk_to_string(thr, -2);
39504 	duk_to_string(thr, -1);
39505 	duk_regexp_compile(thr);
39506 
39507 	/* [ ... bytecode escaped_source ] */
39508 
39509 	duk_regexp_create_instance(thr);
39510 
39511 	/* [ ... RegExp ] */
39512 
39513 	return 1;
39514 }
39515 
39516 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_exec(duk_hthread *thr) {
39517 	duk__get_this_regexp(thr);
39518 
39519 	/* [ regexp input ] */
39520 
39521 	duk_regexp_match(thr);
39522 
39523 	/* [ result ] */
39524 
39525 	return 1;
39526 }
39527 
39528 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_test(duk_hthread *thr) {
39529 	duk__get_this_regexp(thr);
39530 
39531 	/* [ regexp input ] */
39532 
39533 	/* result object is created and discarded; wasteful but saves code space */
39534 	duk_regexp_match(thr);
39535 
39536 	/* [ result ] */
39537 
39538 	duk_push_boolean(thr, (duk_is_null(thr, -1) ? 0 : 1));
39539 
39540 	return 1;
39541 }
39542 
39543 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_tostring(duk_hthread *thr) {
39544 	/* This must be generic in ES2015 and later. */
39545 	DUK_ASSERT_TOP(thr, 0);
39546 	duk_push_this(thr);
39547 	duk_push_literal(thr, "/");
39548 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_SOURCE);
39549 	duk_dup_m2(thr);  /* another "/" */
39550 	duk_get_prop_stridx(thr, 0, DUK_STRIDX_FLAGS);
39551 	duk_concat(thr, 4);
39552 	return 1;
39553 }
39554 
39555 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_flags(duk_hthread *thr) {
39556 	/* .flags is ES2015 but present even when ES2015 bindings are
39557 	 * disabled because the constructor relies on it.
39558 	 */
39559 	duk_uint8_t buf[8];  /* enough for all flags + NUL */
39560 	duk_uint8_t *p = buf;
39561 
39562 	/* .flags is generic and works on any object. */
39563 	duk_push_this(thr);
39564 	(void) duk_require_hobject(thr, -1);
39565 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL)) {
39566 		*p++ = DUK_ASC_LC_G;
39567 	}
39568 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_IGNORE_CASE, NULL)) {
39569 		*p++ = DUK_ASC_LC_I;
39570 	}
39571 	if (duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_MULTILINE, NULL)) {
39572 		*p++ = DUK_ASC_LC_M;
39573 	}
39574 	/* .unicode: to be added */
39575 	/* .sticky: to be added */
39576 	*p++ = DUK_ASC_NUL;
39577 	DUK_ASSERT((duk_size_t) (p - buf) <= sizeof(buf));
39578 
39579 	duk_push_string(thr, (const char *) buf);
39580 	return 1;
39581 }
39582 
39583 /* Shared helper for providing .source, .global, .multiline, etc getters. */
39584 DUK_INTERNAL duk_ret_t duk_bi_regexp_prototype_shared_getter(duk_hthread *thr) {
39585 	duk_hstring *h_bc;
39586 	duk_small_uint_t re_flags;
39587 	duk_hobject *h;
39588 	duk_int_t magic;
39589 
39590 	DUK_ASSERT_TOP(thr, 0);
39591 
39592 	duk_push_this(thr);
39593 	h = duk_require_hobject(thr, -1);
39594 	magic = duk_get_current_magic(thr);
39595 
39596 	if (DUK_HOBJECT_GET_CLASS_NUMBER(h) == DUK_HOBJECT_CLASS_REGEXP) {
39597 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_SOURCE);
39598 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_INT_BYTECODE);
39599 		h_bc = duk_require_hstring(thr, -1);
39600 		re_flags = (duk_small_uint_t) DUK_HSTRING_GET_DATA(h_bc)[0];  /* Safe even if h_bc length is 0 (= NUL) */
39601 		duk_pop(thr);
39602 	} else if (h == thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]) {
39603 		/* In ES2015 and ES2016 a TypeError would be thrown here.
39604 		 * However, this had real world issues so ES2017 draft
39605 		 * allows RegExp.prototype specifically, returning '(?:)'
39606 		 * for .source and undefined for all flags.
39607 		 */
39608 		if (magic != 16 /* .source */) {
39609 			return 0;
39610 		}
39611 		duk_push_literal(thr, "(?:)");  /* .source handled by switch-case */
39612 		re_flags = 0;
39613 	} else {
39614 		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39615 	}
39616 
39617 	/* [ regexp source ] */
39618 
39619 	switch (magic) {
39620 	case 0: {  /* global */
39621 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_GLOBAL));
39622 		break;
39623 	}
39624 	case 1: {  /* ignoreCase */
39625 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_IGNORE_CASE));
39626 		break;
39627 	}
39628 	case 2: {  /* multiline */
39629 		duk_push_boolean(thr, (re_flags & DUK_RE_FLAG_MULTILINE));
39630 		break;
39631 	}
39632 #if 0
39633 	/* Don't provide until implemented to avoid interfering with feature
39634 	 * detection in user code.
39635 	 */
39636 	case 3:    /* sticky */
39637 	case 4: {  /* unicode */
39638 		duk_push_false(thr);
39639 		break;
39640 	}
39641 #endif
39642 	default: {  /* source */
39643 		/* leave 'source' on top */
39644 		break;
39645 	}
39646 	}
39647 
39648 	return 1;
39649 }
39650 
39651 #endif  /* DUK_USE_REGEXP_SUPPORT */
39652 #line 1 "duk_bi_string.c"
39653 /*
39654  *  String built-ins
39655  *
39656  *  Most String built-ins must only accept strings (or String objects).
39657  *  Symbols, represented internally as strings, must be generally rejected.
39658  *  The duk_push_this_coercible_to_string() helper does this automatically.
39659  */
39660 
39661 /* XXX: There are several limitations in the current implementation for
39662  * strings with >= 0x80000000UL characters.  In some cases one would need
39663  * to be able to represent the range [-0xffffffff,0xffffffff] and so on.
39664  * Generally character and byte length are assumed to fit into signed 32
39665  * bits (< 0x80000000UL).  Places with issues are not marked explicitly
39666  * below in all cases, look for signed type usage (duk_int_t etc) for
39667  * offsets/lengths.
39668  */
39669 
39670 /* #include duk_internal.h -> already included */
39671 
39672 #if defined(DUK_USE_STRING_BUILTIN)
39673 
39674 /*
39675  *  Helpers
39676  */
39677 
39678 DUK_LOCAL duk_hstring *duk__str_tostring_notregexp(duk_hthread *thr, duk_idx_t idx) {
39679 	duk_hstring *h;
39680 
39681 	if (duk_get_class_number(thr, idx) == DUK_HOBJECT_CLASS_REGEXP) {
39682 		DUK_ERROR_TYPE_INVALID_ARGS(thr);
39683 		DUK_WO_NORETURN(return NULL;);
39684 	}
39685 	h = duk_to_hstring(thr, idx);
39686 	DUK_ASSERT(h != NULL);
39687 
39688 	return h;
39689 }
39690 
39691 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) {
39692 	duk_int_t cpos;
39693 	duk_int_t bpos;
39694 	const duk_uint8_t *p_start, *p_end, *p;
39695 	const duk_uint8_t *q_start;
39696 	duk_int_t q_blen;
39697 	duk_uint8_t firstbyte;
39698 	duk_uint8_t t;
39699 
39700 	cpos = start_cpos;
39701 
39702 	/* Empty searchstring always matches; cpos must be clamped here.
39703 	 * (If q_blen were < 0 due to clamped coercion, it would also be
39704 	 * caught here.)
39705 	 */
39706 	q_start = DUK_HSTRING_GET_DATA(h_search);
39707 	q_blen = (duk_int_t) DUK_HSTRING_GET_BYTELEN(h_search);
39708 	if (q_blen <= 0) {
39709 		return cpos;
39710 	}
39711 	DUK_ASSERT(q_blen > 0);
39712 
39713 	bpos = (duk_int_t) duk_heap_strcache_offset_char2byte(thr, h_this, (duk_uint32_t) cpos);
39714 
39715 	p_start = DUK_HSTRING_GET_DATA(h_this);
39716 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_this);
39717 	p = p_start + bpos;
39718 
39719 	/* This loop is optimized for size.  For speed, there should be
39720 	 * two separate loops, and we should ensure that memcmp() can be
39721 	 * used without an extra "will searchstring fit" check.  Doing
39722 	 * the preconditioning for 'p' and 'p_end' is easy but cpos
39723 	 * must be updated if 'p' is wound back (backward scanning).
39724 	 */
39725 
39726 	firstbyte = q_start[0];  /* leading byte of match string */
39727 	while (p <= p_end && p >= p_start) {
39728 		t = *p;
39729 
39730 		/* For ECMAScript strings, this check can only match for
39731 		 * initial UTF-8 bytes (not continuation bytes).  For other
39732 		 * strings all bets are off.
39733 		 */
39734 
39735 		if ((t == firstbyte) && ((duk_size_t) (p_end - p) >= (duk_size_t) q_blen)) {
39736 			DUK_ASSERT(q_blen > 0);
39737 			if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
39738 				return cpos;
39739 			}
39740 		}
39741 
39742 		/* track cpos while scanning */
39743 		if (backwards) {
39744 			/* when going backwards, we decrement cpos 'early';
39745 			 * 'p' may point to a continuation byte of the char
39746 			 * at offset 'cpos', but that's OK because we'll
39747 			 * backtrack all the way to the initial byte.
39748 			 */
39749 			if ((t & 0xc0) != 0x80) {
39750 				cpos--;
39751 			}
39752 			p--;
39753 		} else {
39754 			if ((t & 0xc0) != 0x80) {
39755 				cpos++;
39756 			}
39757 			p++;
39758 		}
39759 	}
39760 
39761 	/* Not found.  Empty string case is handled specially above. */
39762 	return -1;
39763 }
39764 
39765 /*
39766  *  Constructor
39767  */
39768 
39769 DUK_INTERNAL duk_ret_t duk_bi_string_constructor(duk_hthread *thr) {
39770 	duk_hstring *h;
39771 	duk_uint_t flags;
39772 
39773 	/* String constructor needs to distinguish between an argument not given at all
39774 	 * vs. given as 'undefined'.  We're a vararg function to handle this properly.
39775 	 */
39776 
39777 	/* XXX: copy current activation flags to thr, including current magic,
39778 	 * is_constructor_call etc.  This takes a few bytes in duk_hthread but
39779 	 * makes call sites smaller (there are >30 is_constructor_call and get
39780 	 * current magic call sites.
39781 	 */
39782 
39783 	if (duk_get_top(thr) == 0) {
39784 		duk_push_hstring_empty(thr);
39785 	} else {
39786 		h = duk_to_hstring_acceptsymbol(thr, 0);
39787 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h) && !duk_is_constructor_call(thr))) {
39788 			duk_push_symbol_descriptive_string(thr, h);
39789 			duk_replace(thr, 0);
39790 		}
39791 	}
39792 	duk_to_string(thr, 0);  /* catches symbol argument for constructor call */
39793 	DUK_ASSERT(duk_is_string(thr, 0));
39794 	duk_set_top(thr, 1);  /* Top may be 1 or larger. */
39795 
39796 	if (duk_is_constructor_call(thr)) {
39797 		/* String object internal value is immutable */
39798 		flags = DUK_HOBJECT_FLAG_EXTENSIBLE |
39799 		        DUK_HOBJECT_FLAG_FASTREFS |
39800 		        DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ |
39801 		        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_STRING);
39802 		duk_push_object_helper(thr, flags, DUK_BIDX_STRING_PROTOTYPE);
39803 		duk_dup_0(thr);
39804 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VALUE, DUK_PROPDESC_FLAGS_NONE);
39805 	}
39806 	/* Note: unbalanced stack on purpose */
39807 
39808 	return 1;
39809 }
39810 
39811 DUK_LOCAL duk_ret_t duk__construct_from_codepoints(duk_hthread *thr, duk_bool_t nonbmp) {
39812 	duk_bufwriter_ctx bw_alloc;
39813 	duk_bufwriter_ctx *bw;
39814 	duk_idx_t i, n;
39815 	duk_ucodepoint_t cp;
39816 
39817 	/* XXX: It would be nice to build the string directly but ToUint16()
39818 	 * coercion is needed so a generic helper would not be very
39819 	 * helpful (perhaps coerce the value stack first here and then
39820 	 * build a string from a duk_tval number sequence in one go?).
39821 	 */
39822 
39823 	n = duk_get_top(thr);
39824 
39825 	bw = &bw_alloc;
39826 	DUK_BW_INIT_PUSHBUF(thr, bw, (duk_size_t) n);  /* initial estimate for ASCII only codepoints */
39827 
39828 	for (i = 0; i < n; i++) {
39829 		/* XXX: could improve bufwriter handling to write multiple codepoints
39830 		 * with one ensure call but the relative benefit would be quite small.
39831 		 */
39832 
39833 		if (nonbmp) {
39834 			/* ES2015 requires that (1) SameValue(cp, ToInteger(cp)) and
39835 			 * (2) cp >= 0 and cp <= 0x10ffff.  This check does not
39836 			 * implement the steps exactly but the outcome should be
39837 			 * the same.
39838 			 */
39839 			duk_int32_t i32 = 0;
39840 			if (!duk_is_whole_get_int32(duk_to_number(thr, i), &i32) ||
39841 			    i32 < 0 || i32 > 0x10ffffL) {
39842 				DUK_DCERROR_RANGE_INVALID_ARGS(thr);
39843 			}
39844 			DUK_ASSERT(i32 >= 0 && i32 <= 0x10ffffL);
39845 			cp = (duk_ucodepoint_t) i32;
39846 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39847 		} else {
39848 #if defined(DUK_USE_NONSTD_STRING_FROMCHARCODE_32BIT)
39849 			/* ToUint16() coercion is mandatory in the E5.1 specification, but
39850 			 * this non-compliant behavior makes more sense because we support
39851 			 * non-BMP codepoints.  Don't use CESU-8 because that'd create
39852 			 * surrogate pairs.
39853 			 */
39854 			cp = (duk_ucodepoint_t) duk_to_uint32(thr, i);
39855 			DUK_BW_WRITE_ENSURE_XUTF8(thr, bw, cp);
39856 #else
39857 			cp = (duk_ucodepoint_t) duk_to_uint16(thr, i);
39858 			DUK_ASSERT(cp >= 0 && cp <= 0x10ffffL);
39859 			DUK_BW_WRITE_ENSURE_CESU8(thr, bw, cp);
39860 #endif
39861 		}
39862 	}
39863 
39864 	DUK_BW_COMPACT(thr, bw);
39865 	(void) duk_buffer_to_string(thr, -1);  /* Safe, extended UTF-8 or CESU-8 encoded. */
39866 	return 1;
39867 }
39868 
39869 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_char_code(duk_hthread *thr) {
39870 	return duk__construct_from_codepoints(thr, 0 /*nonbmp*/);
39871 }
39872 
39873 #if defined(DUK_USE_ES6)
39874 DUK_INTERNAL duk_ret_t duk_bi_string_constructor_from_code_point(duk_hthread *thr) {
39875 	return duk__construct_from_codepoints(thr, 1 /*nonbmp*/);
39876 }
39877 #endif
39878 
39879 /*
39880  *  toString(), valueOf()
39881  */
39882 
39883 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_to_string(duk_hthread *thr) {
39884 	duk_tval *tv;
39885 
39886 	duk_push_this(thr);
39887 	tv = duk_require_tval(thr, -1);
39888 	DUK_ASSERT(tv != NULL);
39889 
39890 	if (DUK_TVAL_IS_STRING(tv)) {
39891 		/* return as is */
39892 	} else if (DUK_TVAL_IS_OBJECT(tv)) {
39893 		duk_hobject *h = DUK_TVAL_GET_OBJECT(tv);
39894 		DUK_ASSERT(h != NULL);
39895 
39896 		/* Must be a "string object", i.e. class "String" */
39897 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h) != DUK_HOBJECT_CLASS_STRING) {
39898 			goto type_error;
39899 		}
39900 
39901 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VALUE);
39902 		DUK_ASSERT(duk_is_string(thr, -1));
39903 	} else {
39904 		goto type_error;
39905 	}
39906 
39907 	(void) duk_require_hstring_notsymbol(thr, -1);  /* Reject symbols (and wrapped symbols). */
39908 	return 1;
39909 
39910  type_error:
39911 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
39912 }
39913 
39914 /*
39915  *  Character and charcode access
39916  */
39917 
39918 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_at(duk_hthread *thr) {
39919 	duk_hstring *h;
39920 	duk_int_t pos;
39921 
39922 	/* XXX: faster implementation */
39923 
39924 	h = duk_push_this_coercible_to_string(thr);
39925 	DUK_ASSERT(h != NULL);
39926 
39927 	pos = duk_to_int(thr, 0);
39928 
39929 	if (sizeof(duk_size_t) >= sizeof(duk_uint_t)) {
39930 		/* Cast to duk_size_t works in this case:
39931 		 * - If pos < 0, (duk_size_t) pos will always be
39932 		 *   >= max_charlen, and result will be the empty string
39933 		 *   (see duk_substring()).
39934 		 * - If pos >= 0, pos + 1 cannot wrap.
39935 		 */
39936 		DUK_ASSERT((duk_size_t) DUK_INT_MIN >= DUK_HSTRING_MAX_BYTELEN);
39937 		DUK_ASSERT((duk_size_t) DUK_INT_MAX + 1U > (duk_size_t) DUK_INT_MAX);
39938 		duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
39939 	} else {
39940 		/* If size_t is smaller than int, explicit bounds checks
39941 		 * are needed because an int may wrap multiple times.
39942 		 */
39943 		if (DUK_UNLIKELY(pos < 0 || (duk_uint_t) pos >= (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h))) {
39944 			duk_push_hstring_empty(thr);
39945 		} else {
39946 			duk_substring(thr, -1, (duk_size_t) pos, (duk_size_t) pos + 1U);
39947 		}
39948 	}
39949 
39950 	return 1;
39951 }
39952 
39953 /* Magic: 0=charCodeAt, 1=codePointAt */
39954 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_char_code_at(duk_hthread *thr) {
39955 	duk_int_t pos;
39956 	duk_hstring *h;
39957 	duk_bool_t clamped;
39958 	duk_uint32_t cp;
39959 	duk_int_t magic;
39960 
39961 	/* XXX: faster implementation */
39962 
39963 	DUK_DDD(DUK_DDDPRINT("arg=%!T", (duk_tval *) duk_get_tval(thr, 0)));
39964 
39965 	h = duk_push_this_coercible_to_string(thr);
39966 	DUK_ASSERT(h != NULL);
39967 
39968 	pos = duk_to_int_clamped_raw(thr,
39969 	                             0 /*index*/,
39970 	                             0 /*min(incl)*/,
39971 	                             (duk_int_t) DUK_HSTRING_GET_CHARLEN(h) - 1 /*max(incl)*/,
39972 	                             &clamped /*out_clamped*/);
39973 #if defined(DUK_USE_ES6)
39974 	magic = duk_get_current_magic(thr);
39975 #else
39976 	DUK_ASSERT(duk_get_current_magic(thr) == 0);
39977 	magic = 0;
39978 #endif
39979 	if (clamped) {
39980 		/* For out-of-bounds indices .charCodeAt() returns NaN and
39981 		 * .codePointAt() returns undefined.
39982 		 */
39983 		if (magic != 0) {
39984 			return 0;
39985 		}
39986 		duk_push_nan(thr);
39987 	} else {
39988 		DUK_ASSERT(pos >= 0);
39989 		cp = (duk_uint32_t) duk_hstring_char_code_at_raw(thr, h, (duk_uint_t) pos, (duk_bool_t) magic /*surrogate_aware*/);
39990 		duk_push_u32(thr, cp);
39991 	}
39992 	return 1;
39993 }
39994 
39995 /*
39996  *  substring(), substr(), slice()
39997  */
39998 
39999 /* XXX: any chance of merging these three similar but still slightly
40000  * different algorithms so that footprint would be reduced?
40001  */
40002 
40003 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substring(duk_hthread *thr) {
40004 	duk_hstring *h;
40005 	duk_int_t start_pos, end_pos;
40006 	duk_int_t len;
40007 
40008 	h = duk_push_this_coercible_to_string(thr);
40009 	DUK_ASSERT(h != NULL);
40010 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40011 
40012 	/* [ start end str ] */
40013 
40014 	start_pos = duk_to_int_clamped(thr, 0, 0, len);
40015 	if (duk_is_undefined(thr, 1)) {
40016 		end_pos = len;
40017 	} else {
40018 		end_pos = duk_to_int_clamped(thr, 1, 0, len);
40019 	}
40020 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40021 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40022 
40023 	if (start_pos > end_pos) {
40024 		duk_int_t tmp = start_pos;
40025 		start_pos = end_pos;
40026 		end_pos = tmp;
40027 	}
40028 
40029 	DUK_ASSERT(end_pos >= start_pos);
40030 
40031 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40032 	return 1;
40033 }
40034 
40035 #if defined(DUK_USE_SECTION_B)
40036 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_substr(duk_hthread *thr) {
40037 	duk_hstring *h;
40038 	duk_int_t start_pos, end_pos;
40039 	duk_int_t len;
40040 
40041 	/* Unlike non-obsolete String calls, substr() algorithm in E5.1
40042 	 * specification will happily coerce undefined and null to strings
40043 	 * ("undefined" and "null").
40044 	 */
40045 	duk_push_this(thr);
40046 	h = duk_to_hstring_m1(thr);  /* Reject Symbols. */
40047 	DUK_ASSERT(h != NULL);
40048 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40049 
40050 	/* [ start length str ] */
40051 
40052 	/* The implementation for computing of start_pos and end_pos differs
40053 	 * from the standard algorithm, but is intended to result in the exactly
40054 	 * same behavior.  This is not always obvious.
40055 	 */
40056 
40057 	/* combines steps 2 and 5; -len ensures max() not needed for step 5 */
40058 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40059 	if (start_pos < 0) {
40060 		start_pos = len + start_pos;
40061 	}
40062 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40063 
40064 	/* combines steps 3, 6; step 7 is not needed */
40065 	if (duk_is_undefined(thr, 1)) {
40066 		end_pos = len;
40067 	} else {
40068 		DUK_ASSERT(start_pos <= len);
40069 		end_pos = start_pos + duk_to_int_clamped(thr, 1, 0, len - start_pos);
40070 	}
40071 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40072 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40073 	DUK_ASSERT(end_pos >= start_pos);
40074 
40075 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40076 	return 1;
40077 }
40078 #endif  /* DUK_USE_SECTION_B */
40079 
40080 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_slice(duk_hthread *thr) {
40081 	duk_hstring *h;
40082 	duk_int_t start_pos, end_pos;
40083 	duk_int_t len;
40084 
40085 	h = duk_push_this_coercible_to_string(thr);
40086 	DUK_ASSERT(h != NULL);
40087 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
40088 
40089 	/* [ start end str ] */
40090 
40091 	start_pos = duk_to_int_clamped(thr, 0, -len, len);
40092 	if (start_pos < 0) {
40093 		start_pos = len + start_pos;
40094 	}
40095 	if (duk_is_undefined(thr, 1)) {
40096 		end_pos = len;
40097 	} else {
40098 		end_pos = duk_to_int_clamped(thr, 1, -len, len);
40099 		if (end_pos < 0) {
40100 			end_pos = len + end_pos;
40101 		}
40102 	}
40103 	DUK_ASSERT(start_pos >= 0 && start_pos <= len);
40104 	DUK_ASSERT(end_pos >= 0 && end_pos <= len);
40105 
40106 	if (end_pos < start_pos) {
40107 		end_pos = start_pos;
40108 	}
40109 
40110 	DUK_ASSERT(end_pos >= start_pos);
40111 
40112 	duk_substring(thr, -1, (duk_size_t) start_pos, (duk_size_t) end_pos);
40113 	return 1;
40114 }
40115 
40116 /*
40117  *  Case conversion
40118  */
40119 
40120 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_caseconv_shared(duk_hthread *thr) {
40121 	duk_small_int_t uppercase = duk_get_current_magic(thr);
40122 
40123 	(void) duk_push_this_coercible_to_string(thr);
40124 	duk_unicode_case_convert_string(thr, (duk_bool_t) uppercase);
40125 	return 1;
40126 }
40127 
40128 /*
40129  *  indexOf() and lastIndexOf()
40130  */
40131 
40132 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_indexof_shared(duk_hthread *thr) {
40133 	duk_hstring *h_this;
40134 	duk_hstring *h_search;
40135 	duk_int_t clen_this;
40136 	duk_int_t cpos;
40137 	duk_small_uint_t is_lastindexof = (duk_small_uint_t) duk_get_current_magic(thr);  /* 0=indexOf, 1=lastIndexOf */
40138 
40139 	h_this = duk_push_this_coercible_to_string(thr);
40140 	DUK_ASSERT(h_this != NULL);
40141 	clen_this = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h_this);
40142 
40143 	h_search = duk_to_hstring(thr, 0);
40144 	DUK_ASSERT(h_search != NULL);
40145 
40146 	duk_to_number(thr, 1);
40147 	if (duk_is_nan(thr, 1) && is_lastindexof) {
40148 		/* indexOf: NaN should cause pos to be zero.
40149 		 * lastIndexOf: NaN should cause pos to be +Infinity
40150 		 * (and later be clamped to len).
40151 		 */
40152 		cpos = clen_this;
40153 	} else {
40154 		cpos = duk_to_int_clamped(thr, 1, 0, clen_this);
40155 	}
40156 
40157 	cpos = duk__str_search_shared(thr, h_this, h_search, cpos, is_lastindexof /*backwards*/);
40158 	duk_push_int(thr, cpos);
40159 	return 1;
40160 }
40161 
40162 /*
40163  *  replace()
40164  */
40165 
40166 /* XXX: the current implementation works but is quite clunky; it compiles
40167  * to almost 1,4kB of x86 code so it needs to be simplified (better approach,
40168  * shared helpers, etc).  Some ideas for refactoring:
40169  *
40170  * - a primitive to convert a string into a regexp matcher (reduces matching
40171  *   code at the cost of making matching much slower)
40172  * - use replace() as a basic helper for match() and split(), which are both
40173  *   much simpler
40174  * - API call to get_prop and to_boolean
40175  */
40176 
40177 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_replace(duk_hthread *thr) {
40178 	duk_hstring *h_input;
40179 	duk_hstring *h_match;
40180 	duk_hstring *h_search;
40181 	duk_hobject *h_re;
40182 	duk_bufwriter_ctx bw_alloc;
40183 	duk_bufwriter_ctx *bw;
40184 #if defined(DUK_USE_REGEXP_SUPPORT)
40185 	duk_bool_t is_regexp;
40186 	duk_bool_t is_global;
40187 #endif
40188 	duk_bool_t is_repl_func;
40189 	duk_uint32_t match_start_coff, match_start_boff;
40190 #if defined(DUK_USE_REGEXP_SUPPORT)
40191 	duk_int_t match_caps;
40192 #endif
40193 	duk_uint32_t prev_match_end_boff;
40194 	const duk_uint8_t *r_start, *r_end, *r;   /* repl string scan */
40195 	duk_size_t tmp_sz;
40196 
40197 	DUK_ASSERT_TOP(thr, 2);
40198 	h_input = duk_push_this_coercible_to_string(thr);
40199 	DUK_ASSERT(h_input != NULL);
40200 
40201 	bw = &bw_alloc;
40202 	DUK_BW_INIT_PUSHBUF(thr, bw, DUK_HSTRING_GET_BYTELEN(h_input));  /* input size is good output starting point */
40203 
40204 	DUK_ASSERT_TOP(thr, 4);
40205 
40206 	/* stack[0] = search value
40207 	 * stack[1] = replace value
40208 	 * stack[2] = input string
40209 	 * stack[3] = result buffer
40210 	 */
40211 
40212 	h_re = duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP);
40213 	if (h_re) {
40214 #if defined(DUK_USE_REGEXP_SUPPORT)
40215 		is_regexp = 1;
40216 		is_global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
40217 
40218 		if (is_global) {
40219 			/* start match from beginning */
40220 			duk_push_int(thr, 0);
40221 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40222 		}
40223 #else  /* DUK_USE_REGEXP_SUPPORT */
40224 		DUK_DCERROR_UNSUPPORTED(thr);
40225 #endif  /* DUK_USE_REGEXP_SUPPORT */
40226 	} else {
40227 		duk_to_string(thr, 0);  /* rejects symbols */
40228 #if defined(DUK_USE_REGEXP_SUPPORT)
40229 		is_regexp = 0;
40230 		is_global = 0;
40231 #endif
40232 	}
40233 
40234 	if (duk_is_function(thr, 1)) {
40235 		is_repl_func = 1;
40236 		r_start = NULL;
40237 		r_end = NULL;
40238 	} else {
40239 		duk_hstring *h_repl;
40240 
40241 		is_repl_func = 0;
40242 		h_repl = duk_to_hstring(thr, 1);  /* reject symbols */
40243 		DUK_ASSERT(h_repl != NULL);
40244 		r_start = DUK_HSTRING_GET_DATA(h_repl);
40245 		r_end = r_start + DUK_HSTRING_GET_BYTELEN(h_repl);
40246 	}
40247 
40248 	prev_match_end_boff = 0;
40249 
40250 	for (;;) {
40251 		/*
40252 		 *  If matching with a regexp:
40253 		 *    - non-global RegExp: lastIndex not touched on a match, zeroed
40254 		 *      on a non-match
40255 		 *    - global RegExp: on match, lastIndex will be updated by regexp
40256 		 *      executor to point to next char after the matching part (so that
40257 		 *      characters in the matching part are not matched again)
40258 		 *
40259 		 *  If matching with a string:
40260 		 *    - always non-global match, find first occurrence
40261 		 *
40262 		 *  We need:
40263 		 *    - The character offset of start-of-match for the replacer function
40264 		 *    - The byte offsets for start-of-match and end-of-match to implement
40265 		 *      the replacement values $&, $`, and $', and to copy non-matching
40266 		 *      input string portions (including header and trailer) verbatim.
40267 		 *
40268 		 *  NOTE: the E5.1 specification is a bit vague how the RegExp should
40269 		 *  behave in the replacement process; e.g. is matching done first for
40270 		 *  all matches (in the global RegExp case) before any replacer calls
40271 		 *  are made?  See: test-bi-string-proto-replace.js for discussion.
40272 		 */
40273 
40274 		DUK_ASSERT_TOP(thr, 4);
40275 
40276 #if defined(DUK_USE_REGEXP_SUPPORT)
40277 		if (is_regexp) {
40278 			duk_dup_0(thr);
40279 			duk_dup_2(thr);
40280 			duk_regexp_match(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40281 			if (!duk_is_object(thr, -1)) {
40282 				duk_pop(thr);
40283 				break;
40284 			}
40285 
40286 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40287 			DUK_ASSERT(duk_is_number(thr, -1));
40288 			match_start_coff = duk_get_uint(thr, -1);
40289 			duk_pop(thr);
40290 
40291 			duk_get_prop_index(thr, -1, 0);
40292 			DUK_ASSERT(duk_is_string(thr, -1));
40293 			h_match = duk_known_hstring(thr, -1);
40294 			duk_pop(thr);  /* h_match is borrowed, remains reachable through match_obj */
40295 
40296 			if (DUK_HSTRING_GET_BYTELEN(h_match) == 0) {
40297 				/* This should be equivalent to match() algorithm step 8.f.iii.2:
40298 				 * detect an empty match and allow it, but don't allow it twice.
40299 				 */
40300 				duk_uint32_t last_index;
40301 
40302 				duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40303 				last_index = (duk_uint32_t) duk_get_uint(thr, -1);
40304 				DUK_DDD(DUK_DDDPRINT("empty match, bump lastIndex: %ld -> %ld",
40305 				                     (long) last_index, (long) (last_index + 1)));
40306 				duk_pop(thr);
40307 				duk_push_uint(thr, (duk_uint_t) (last_index + 1));
40308 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40309 			}
40310 
40311 			DUK_ASSERT(duk_get_length(thr, -1) <= DUK_INT_MAX);  /* string limits */
40312 			match_caps = (duk_int_t) duk_get_length(thr, -1);
40313 		} else {
40314 #else  /* DUK_USE_REGEXP_SUPPORT */
40315 		{  /* unconditionally */
40316 #endif  /* DUK_USE_REGEXP_SUPPORT */
40317 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40318 			const duk_uint8_t *q_start;               /* match string */
40319 			duk_size_t q_blen;
40320 
40321 #if defined(DUK_USE_REGEXP_SUPPORT)
40322 			DUK_ASSERT(!is_global);  /* single match always */
40323 #endif
40324 
40325 			p_start = DUK_HSTRING_GET_DATA(h_input);
40326 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40327 			p = p_start;
40328 
40329 			h_search = duk_known_hstring(thr, 0);
40330 			q_start = DUK_HSTRING_GET_DATA(h_search);
40331 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_search);
40332 
40333 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40334 
40335 			match_start_coff = 0;
40336 
40337 			while (p <= p_end) {
40338 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40339 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40340 					duk_dup_0(thr);
40341 					h_match = duk_known_hstring(thr, -1);
40342 #if defined(DUK_USE_REGEXP_SUPPORT)
40343 					match_caps = 0;
40344 #endif
40345 					goto found;
40346 				}
40347 
40348 				/* track utf-8 non-continuation bytes */
40349 				if ((p[0] & 0xc0) != 0x80) {
40350 					match_start_coff++;
40351 				}
40352 				p++;
40353 			}
40354 
40355 			/* not found */
40356 			break;
40357 		}
40358 	 found:
40359 
40360 		/* stack[0] = search value
40361 		 * stack[1] = replace value
40362 		 * stack[2] = input string
40363 		 * stack[3] = result buffer
40364 		 * stack[4] = regexp match OR match string
40365 		 */
40366 
40367 		match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40368 
40369 		tmp_sz = (duk_size_t) (match_start_boff - prev_match_end_boff);
40370 		DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40371 
40372 		prev_match_end_boff = match_start_boff + DUK_HSTRING_GET_BYTELEN(h_match);
40373 
40374 		if (is_repl_func) {
40375 			duk_idx_t idx_args;
40376 			duk_hstring *h_repl;
40377 
40378 			/* regexp res_obj is at index 4 */
40379 
40380 			duk_dup_1(thr);
40381 			idx_args = duk_get_top(thr);
40382 
40383 #if defined(DUK_USE_REGEXP_SUPPORT)
40384 			if (is_regexp) {
40385 				duk_int_t idx;
40386 				duk_require_stack(thr, match_caps + 2);
40387 				for (idx = 0; idx < match_caps; idx++) {
40388 					/* match followed by capture(s) */
40389 					duk_get_prop_index(thr, 4, (duk_uarridx_t) idx);
40390 				}
40391 			} else {
40392 #else  /* DUK_USE_REGEXP_SUPPORT */
40393 			{  /* unconditionally */
40394 #endif  /* DUK_USE_REGEXP_SUPPORT */
40395 				/* match == search string, by definition */
40396 				duk_dup_0(thr);
40397 			}
40398 			duk_push_uint(thr, (duk_uint_t) match_start_coff);
40399 			duk_dup_2(thr);
40400 
40401 			/* [ ... replacer match [captures] match_char_offset input ] */
40402 
40403 			duk_call(thr, duk_get_top(thr) - idx_args);
40404 			h_repl = duk_to_hstring_m1(thr);  /* -> [ ... repl_value ] */
40405 			DUK_ASSERT(h_repl != NULL);
40406 
40407 			DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_repl);
40408 
40409 			duk_pop(thr);  /* repl_value */
40410 		} else {
40411 			r = r_start;
40412 
40413 			while (r < r_end) {
40414 				duk_int_t ch1;
40415 				duk_int_t ch2;
40416 #if defined(DUK_USE_REGEXP_SUPPORT)
40417 				duk_int_t ch3;
40418 #endif
40419 				duk_size_t left;
40420 
40421 				ch1 = *r++;
40422 				if (ch1 != DUK_ASC_DOLLAR) {
40423 					goto repl_write;
40424 				}
40425 				DUK_ASSERT(r <= r_end);
40426 				left = (duk_size_t) (r_end - r);
40427 
40428 				if (left <= 0) {
40429 					goto repl_write;
40430 				}
40431 
40432 				ch2 = r[0];
40433 				switch (ch2) {
40434 				case DUK_ASC_DOLLAR: {
40435 					ch1 = (1 << 8) + DUK_ASC_DOLLAR;
40436 					goto repl_write;
40437 				}
40438 				case DUK_ASC_AMP: {
40439 					DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_match);
40440 					r++;
40441 					continue;
40442 				}
40443 				case DUK_ASC_GRAVE: {
40444 					tmp_sz = (duk_size_t) match_start_boff;
40445 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input), tmp_sz);
40446 					r++;
40447 					continue;
40448 				}
40449 				case DUK_ASC_SINGLEQUOTE: {
40450 					duk_uint32_t match_end_boff;
40451 
40452 					/* Use match charlen instead of bytelen, just in case the input and
40453 					 * match codepoint encodings would have different lengths.
40454 					 */
40455 					/* XXX: charlen computed here, and also in char2byte helper. */
40456 					match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr,
40457 					                                                                   h_input,
40458 					                                                                   match_start_coff + (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_match));
40459 
40460 					tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - match_end_boff);
40461 					DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + match_end_boff, tmp_sz);
40462 					r++;
40463 					continue;
40464 				}
40465 				default: {
40466 #if defined(DUK_USE_REGEXP_SUPPORT)
40467 					duk_int_t capnum, captmp, capadv;
40468 					/* XXX: optional check, match_caps is zero if no regexp,
40469 					 * so dollar will be interpreted literally anyway.
40470 					 */
40471 
40472 					if (!is_regexp) {
40473 						goto repl_write;
40474 					}
40475 
40476 					if (!(ch2 >= DUK_ASC_0 && ch2 <= DUK_ASC_9)) {
40477 						goto repl_write;
40478 					}
40479 					capnum = ch2 - DUK_ASC_0;
40480 					capadv = 1;
40481 
40482 					if (left >= 2) {
40483 						ch3 = r[1];
40484 						if (ch3 >= DUK_ASC_0 && ch3 <= DUK_ASC_9) {
40485 							captmp = capnum * 10 + (ch3 - DUK_ASC_0);
40486 							if (captmp < match_caps) {
40487 								capnum = captmp;
40488 								capadv = 2;
40489 							}
40490 						}
40491 					}
40492 
40493 					if (capnum > 0 && capnum < match_caps) {
40494 						DUK_ASSERT(is_regexp != 0);  /* match_caps == 0 without regexps */
40495 
40496 						/* regexp res_obj is at offset 4 */
40497 						duk_get_prop_index(thr, 4, (duk_uarridx_t) capnum);
40498 						if (duk_is_string(thr, -1)) {
40499 							duk_hstring *h_tmp_str;
40500 
40501 							h_tmp_str = duk_known_hstring(thr, -1);
40502 
40503 							DUK_BW_WRITE_ENSURE_HSTRING(thr, bw, h_tmp_str);
40504 						} else {
40505 							/* undefined -> skip (replaced with empty) */
40506 						}
40507 						duk_pop(thr);
40508 						r += capadv;
40509 						continue;
40510 					} else {
40511 						goto repl_write;
40512 					}
40513 #else  /* DUK_USE_REGEXP_SUPPORT */
40514 					goto repl_write;  /* unconditionally */
40515 #endif  /* DUK_USE_REGEXP_SUPPORT */
40516 				}  /* default case */
40517 				}  /* switch (ch2) */
40518 
40519 			 repl_write:
40520 				/* ch1 = (r_increment << 8) + byte */
40521 
40522 				DUK_BW_WRITE_ENSURE_U8(thr, bw, (duk_uint8_t) (ch1 & 0xff));
40523 				r += ch1 >> 8;
40524 			}  /* while repl */
40525 		}  /* if (is_repl_func) */
40526 
40527 		duk_pop(thr);  /* pop regexp res_obj or match string */
40528 
40529 #if defined(DUK_USE_REGEXP_SUPPORT)
40530 		if (!is_global) {
40531 #else
40532 		{  /* unconditionally; is_global==0 */
40533 #endif
40534 			break;
40535 		}
40536 	}
40537 
40538 	/* trailer */
40539 	tmp_sz = (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff);
40540 	DUK_BW_WRITE_ENSURE_BYTES(thr, bw, DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff, tmp_sz);
40541 
40542 	DUK_ASSERT_TOP(thr, 4);
40543 	DUK_BW_COMPACT(thr, bw);
40544 	(void) duk_buffer_to_string(thr, -1);  /* Safe if inputs are safe. */
40545 	return 1;
40546 }
40547 
40548 /*
40549  *  split()
40550  */
40551 
40552 /* XXX: very messy now, but works; clean up, remove unused variables (nomimally
40553  * used so compiler doesn't complain).
40554  */
40555 
40556 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_split(duk_hthread *thr) {
40557 	duk_hstring *h_input;
40558 	duk_hstring *h_sep;
40559 	duk_uint32_t limit;
40560 	duk_uint32_t arr_idx;
40561 #if defined(DUK_USE_REGEXP_SUPPORT)
40562 	duk_bool_t is_regexp;
40563 #endif
40564 	duk_bool_t matched;  /* set to 1 if any match exists (needed for empty input special case) */
40565 	duk_uint32_t prev_match_end_coff, prev_match_end_boff;
40566 	duk_uint32_t match_start_boff, match_start_coff;
40567 	duk_uint32_t match_end_boff, match_end_coff;
40568 
40569 	h_input = duk_push_this_coercible_to_string(thr);
40570 	DUK_ASSERT(h_input != NULL);
40571 
40572 	duk_push_array(thr);
40573 
40574 	if (duk_is_undefined(thr, 1)) {
40575 		limit = 0xffffffffUL;
40576 	} else {
40577 		limit = duk_to_uint32(thr, 1);
40578 	}
40579 
40580 	if (limit == 0) {
40581 		return 1;
40582 	}
40583 
40584 	/* If the separator is a RegExp, make a "clone" of it.  The specification
40585 	 * algorithm calls [[Match]] directly for specific indices; we emulate this
40586 	 * by tweaking lastIndex and using a "force global" variant of duk_regexp_match()
40587 	 * which will use global-style matching even when the RegExp itself is non-global.
40588 	 */
40589 
40590 	if (duk_is_undefined(thr, 0)) {
40591 		/* The spec algorithm first does "R = ToString(separator)" before checking
40592 		 * whether separator is undefined.  Since this is side effect free, we can
40593 		 * skip the ToString() here.
40594 		 */
40595 		duk_dup_2(thr);
40596 		duk_put_prop_index(thr, 3, 0);
40597 		return 1;
40598 	} else if (duk_get_hobject_with_class(thr, 0, DUK_HOBJECT_CLASS_REGEXP) != NULL) {
40599 #if defined(DUK_USE_REGEXP_SUPPORT)
40600 		duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40601 		duk_dup_0(thr);
40602 		duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40603 		duk_replace(thr, 0);
40604 		/* lastIndex is initialized to zero by new RegExp() */
40605 		is_regexp = 1;
40606 #else
40607 		DUK_DCERROR_UNSUPPORTED(thr);
40608 #endif
40609 	} else {
40610 		duk_to_string(thr, 0);
40611 #if defined(DUK_USE_REGEXP_SUPPORT)
40612 		is_regexp = 0;
40613 #endif
40614 	}
40615 
40616 	/* stack[0] = separator (string or regexp)
40617 	 * stack[1] = limit
40618 	 * stack[2] = input string
40619 	 * stack[3] = result array
40620 	 */
40621 
40622 	prev_match_end_boff = 0;
40623 	prev_match_end_coff = 0;
40624 	arr_idx = 0;
40625 	matched = 0;
40626 
40627 	for (;;) {
40628 		/*
40629 		 *  The specification uses RegExp [[Match]] to attempt match at specific
40630 		 *  offsets.  We don't have such a primitive, so we use an actual RegExp
40631 		 *  and tweak lastIndex.  Since the RegExp may be non-global, we use a
40632 		 *  special variant which forces global-like behavior for matching.
40633 		 */
40634 
40635 		DUK_ASSERT_TOP(thr, 4);
40636 
40637 #if defined(DUK_USE_REGEXP_SUPPORT)
40638 		if (is_regexp) {
40639 			duk_dup_0(thr);
40640 			duk_dup_2(thr);
40641 			duk_regexp_match_force_global(thr);  /* [ ... regexp input ] -> [ res_obj ] */
40642 			if (!duk_is_object(thr, -1)) {
40643 				duk_pop(thr);
40644 				break;
40645 			}
40646 			matched = 1;
40647 
40648 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40649 			DUK_ASSERT(duk_is_number(thr, -1));
40650 			match_start_coff = duk_get_uint(thr, -1);
40651 			match_start_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_start_coff);
40652 			duk_pop(thr);
40653 
40654 			if (match_start_coff == DUK_HSTRING_GET_CHARLEN(h_input)) {
40655 				/* don't allow an empty match at the end of the string */
40656 				duk_pop(thr);
40657 				break;
40658 			}
40659 
40660 			duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40661 			DUK_ASSERT(duk_is_number(thr, -1));
40662 			match_end_coff = duk_get_uint(thr, -1);
40663 			match_end_boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h_input, match_end_coff);
40664 			duk_pop(thr);
40665 
40666 			/* empty match -> bump and continue */
40667 			if (prev_match_end_boff == match_end_boff) {
40668 				duk_push_uint(thr, (duk_uint_t) (match_end_coff + 1));
40669 				duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40670 				duk_pop(thr);
40671 				continue;
40672 			}
40673 		} else {
40674 #else  /* DUK_USE_REGEXP_SUPPORT */
40675 		{  /* unconditionally */
40676 #endif  /* DUK_USE_REGEXP_SUPPORT */
40677 			const duk_uint8_t *p_start, *p_end, *p;   /* input string scan */
40678 			const duk_uint8_t *q_start;               /* match string */
40679 			duk_size_t q_blen, q_clen;
40680 
40681 			p_start = DUK_HSTRING_GET_DATA(h_input);
40682 			p_end = p_start + DUK_HSTRING_GET_BYTELEN(h_input);
40683 			p = p_start + prev_match_end_boff;
40684 
40685 			h_sep = duk_known_hstring(thr, 0);  /* symbol already rejected above */
40686 			q_start = DUK_HSTRING_GET_DATA(h_sep);
40687 			q_blen = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h_sep);
40688 			q_clen = (duk_size_t) DUK_HSTRING_GET_CHARLEN(h_sep);
40689 
40690 			p_end -= q_blen;  /* ensure full memcmp() fits in while */
40691 
40692 			match_start_coff = prev_match_end_coff;
40693 
40694 			if (q_blen == 0) {
40695 				/* Handle empty separator case: it will always match, and always
40696 				 * triggers the check in step 13.c.iii initially.  Note that we
40697 				 * must skip to either end of string or start of first codepoint,
40698 				 * skipping over any continuation bytes!
40699 				 *
40700 				 * Don't allow an empty string to match at the end of the input.
40701 				 */
40702 
40703 				matched = 1;  /* empty separator can always match */
40704 
40705 				match_start_coff++;
40706 				p++;
40707 				while (p < p_end) {
40708 					if ((p[0] & 0xc0) != 0x80) {
40709 						goto found;
40710 					}
40711 					p++;
40712 				}
40713 				goto not_found;
40714 			}
40715 
40716 			DUK_ASSERT(q_blen > 0 && q_clen > 0);
40717 			while (p <= p_end) {
40718 				DUK_ASSERT(p + q_blen <= DUK_HSTRING_GET_DATA(h_input) + DUK_HSTRING_GET_BYTELEN(h_input));
40719 				DUK_ASSERT(q_blen > 0);  /* no issues with empty memcmp() */
40720 				if (duk_memcmp((const void *) p, (const void *) q_start, (size_t) q_blen) == 0) {
40721 					/* never an empty match, so step 13.c.iii can't be triggered */
40722 					goto found;
40723 				}
40724 
40725 				/* track utf-8 non-continuation bytes */
40726 				if ((p[0] & 0xc0) != 0x80) {
40727 					match_start_coff++;
40728 				}
40729 				p++;
40730 			}
40731 
40732 		 not_found:
40733 			/* not found */
40734 			break;
40735 
40736 		 found:
40737 			matched = 1;
40738 			match_start_boff = (duk_uint32_t) (p - p_start);
40739 			match_end_coff = (duk_uint32_t) (match_start_coff + q_clen);  /* constrained by string length */
40740 			match_end_boff = (duk_uint32_t) (match_start_boff + q_blen);  /* ditto */
40741 
40742 			/* empty match (may happen with empty separator) -> bump and continue */
40743 			if (prev_match_end_boff == match_end_boff) {
40744 				prev_match_end_boff++;
40745 				prev_match_end_coff++;
40746 				continue;
40747 			}
40748 		}  /* if (is_regexp) */
40749 
40750 		/* stack[0] = separator (string or regexp)
40751 		 * stack[1] = limit
40752 		 * stack[2] = input string
40753 		 * stack[3] = result array
40754 		 * stack[4] = regexp res_obj (if is_regexp)
40755 		 */
40756 
40757 		DUK_DDD(DUK_DDDPRINT("split; match_start b=%ld,c=%ld, match_end b=%ld,c=%ld, prev_end b=%ld,c=%ld",
40758 		                     (long) match_start_boff, (long) match_start_coff,
40759 		                     (long) match_end_boff, (long) match_end_coff,
40760 		                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40761 
40762 		duk_push_lstring(thr,
40763 		                 (const char *) (DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff),
40764 		                 (duk_size_t) (match_start_boff - prev_match_end_boff));
40765 		duk_put_prop_index(thr, 3, arr_idx);
40766 		arr_idx++;
40767 		if (arr_idx >= limit) {
40768 			goto hit_limit;
40769 		}
40770 
40771 #if defined(DUK_USE_REGEXP_SUPPORT)
40772 		if (is_regexp) {
40773 			duk_size_t i, len;
40774 
40775 			len = duk_get_length(thr, 4);
40776 			for (i = 1; i < len; i++) {
40777 				DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* cannot have >4G captures */
40778 				duk_get_prop_index(thr, 4, (duk_uarridx_t) i);
40779 				duk_put_prop_index(thr, 3, arr_idx);
40780 				arr_idx++;
40781 				if (arr_idx >= limit) {
40782 					goto hit_limit;
40783 				}
40784 			}
40785 
40786 			duk_pop(thr);
40787 			/* lastIndex already set up for next match */
40788 		} else {
40789 #else  /* DUK_USE_REGEXP_SUPPORT */
40790 		{  /* unconditionally */
40791 #endif  /* DUK_USE_REGEXP_SUPPORT */
40792 			/* no action */
40793 		}
40794 
40795 		prev_match_end_boff = match_end_boff;
40796 		prev_match_end_coff = match_end_coff;
40797 		continue;
40798 	}  /* for */
40799 
40800 	/* Combined step 11 (empty string special case) and 14-15. */
40801 
40802 	DUK_DDD(DUK_DDDPRINT("split trailer; prev_end b=%ld,c=%ld",
40803 	                     (long) prev_match_end_boff, (long) prev_match_end_coff));
40804 
40805 	if (DUK_HSTRING_GET_BYTELEN(h_input) > 0 || !matched) {
40806 		/* Add trailer if:
40807 		 *   a) non-empty input
40808 		 *   b) empty input and no (zero size) match found (step 11)
40809 		 */
40810 
40811 		duk_push_lstring(thr,
40812 		                 (const char *) DUK_HSTRING_GET_DATA(h_input) + prev_match_end_boff,
40813 		                 (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h_input) - prev_match_end_boff));
40814 		duk_put_prop_index(thr, 3, arr_idx);
40815 		/* No arr_idx update or limit check */
40816 	}
40817 
40818 	return 1;
40819 
40820  hit_limit:
40821 #if defined(DUK_USE_REGEXP_SUPPORT)
40822 	if (is_regexp) {
40823 		duk_pop(thr);
40824 	}
40825 #endif
40826 
40827 	return 1;
40828 }
40829 
40830 /*
40831  *  Various
40832  */
40833 
40834 #if defined(DUK_USE_REGEXP_SUPPORT)
40835 DUK_LOCAL void duk__to_regexp_helper(duk_hthread *thr, duk_idx_t idx, duk_bool_t force_new) {
40836 	duk_hobject *h;
40837 
40838 	/* Shared helper for match() steps 3-4, search() steps 3-4. */
40839 
40840 	DUK_ASSERT(idx >= 0);
40841 
40842 	if (force_new) {
40843 		goto do_new;
40844 	}
40845 
40846 	h = duk_get_hobject_with_class(thr, idx, DUK_HOBJECT_CLASS_REGEXP);
40847 	if (!h) {
40848 		goto do_new;
40849 	}
40850 	return;
40851 
40852  do_new:
40853 	duk_push_hobject_bidx(thr, DUK_BIDX_REGEXP_CONSTRUCTOR);
40854 	duk_dup(thr, idx);
40855 	duk_new(thr, 1);  /* [ ... RegExp val ] -> [ ... res ] */
40856 	duk_replace(thr, idx);
40857 }
40858 #endif  /* DUK_USE_REGEXP_SUPPORT */
40859 
40860 #if defined(DUK_USE_REGEXP_SUPPORT)
40861 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_search(duk_hthread *thr) {
40862 	/* Easiest way to implement the search required by the specification
40863 	 * is to do a RegExp test() with lastIndex forced to zero.  To avoid
40864 	 * side effects on the argument, "clone" the RegExp if a RegExp was
40865 	 * given as input.
40866 	 *
40867 	 * The global flag of the RegExp should be ignored; setting lastIndex
40868 	 * to zero (which happens when "cloning" the RegExp) should have an
40869 	 * equivalent effect.
40870 	 */
40871 
40872 	DUK_ASSERT_TOP(thr, 1);
40873 	(void) duk_push_this_coercible_to_string(thr);  /* at index 1 */
40874 	duk__to_regexp_helper(thr, 0 /*index*/, 1 /*force_new*/);
40875 
40876 	/* stack[0] = regexp
40877 	 * stack[1] = string
40878 	 */
40879 
40880 	/* Avoid using RegExp.prototype methods, as they're writable and
40881 	 * configurable and may have been changed.
40882 	 */
40883 
40884 	duk_dup_0(thr);
40885 	duk_dup_1(thr);  /* [ ... re_obj input ] */
40886 	duk_regexp_match(thr);  /* -> [ ... res_obj ] */
40887 
40888 	if (!duk_is_object(thr, -1)) {
40889 		duk_push_int(thr, -1);
40890 		return 1;
40891 	}
40892 
40893 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INDEX);
40894 	DUK_ASSERT(duk_is_number(thr, -1));
40895 	return 1;
40896 }
40897 #endif  /* DUK_USE_REGEXP_SUPPORT */
40898 
40899 #if defined(DUK_USE_REGEXP_SUPPORT)
40900 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_match(duk_hthread *thr) {
40901 	duk_bool_t global;
40902 	duk_int_t prev_last_index;
40903 	duk_int_t this_index;
40904 	duk_int_t arr_idx;
40905 
40906 	DUK_ASSERT_TOP(thr, 1);
40907 	(void) duk_push_this_coercible_to_string(thr);
40908 	duk__to_regexp_helper(thr, 0 /*index*/, 0 /*force_new*/);
40909 	global = duk_get_prop_stridx_boolean(thr, 0, DUK_STRIDX_GLOBAL, NULL);
40910 	DUK_ASSERT_TOP(thr, 2);
40911 
40912 	/* stack[0] = regexp
40913 	 * stack[1] = string
40914 	 */
40915 
40916 	if (!global) {
40917 		duk_regexp_match(thr);  /* -> [ res_obj ] */
40918 		return 1;  /* return 'res_obj' */
40919 	}
40920 
40921 	/* Global case is more complex. */
40922 
40923 	/* [ regexp string ] */
40924 
40925 	duk_push_int(thr, 0);
40926 	duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40927 	duk_push_array(thr);
40928 
40929 	/* [ regexp string res_arr ] */
40930 
40931 	prev_last_index = 0;
40932 	arr_idx = 0;
40933 
40934 	for (;;) {
40935 		DUK_ASSERT_TOP(thr, 3);
40936 
40937 		duk_dup_0(thr);
40938 		duk_dup_1(thr);
40939 		duk_regexp_match(thr);  /* -> [ ... regexp string ] -> [ ... res_obj ] */
40940 
40941 		if (!duk_is_object(thr, -1)) {
40942 			duk_pop(thr);
40943 			break;
40944 		}
40945 
40946 		duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40947 		DUK_ASSERT(duk_is_number(thr, -1));
40948 		this_index = duk_get_int(thr, -1);
40949 		duk_pop(thr);
40950 
40951 		if (this_index == prev_last_index) {
40952 			this_index++;
40953 			duk_push_int(thr, this_index);
40954 			duk_put_prop_stridx_short(thr, 0, DUK_STRIDX_LAST_INDEX);
40955 		}
40956 		prev_last_index = this_index;
40957 
40958 		duk_get_prop_index(thr, -1, 0);  /* match string */
40959 		duk_put_prop_index(thr, 2, (duk_uarridx_t) arr_idx);
40960 		arr_idx++;
40961 		duk_pop(thr);  /* res_obj */
40962 	}
40963 
40964 	if (arr_idx == 0) {
40965 		duk_push_null(thr);
40966 	}
40967 
40968 	return 1;  /* return 'res_arr' or 'null' */
40969 }
40970 #endif  /* DUK_USE_REGEXP_SUPPORT */
40971 
40972 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_concat(duk_hthread *thr) {
40973 	/* duk_concat() coerces arguments with ToString() in correct order */
40974 	(void) duk_push_this_coercible_to_string(thr);
40975 	duk_insert(thr, 0);  /* this is relatively expensive */
40976 	duk_concat(thr, duk_get_top(thr));
40977 	return 1;
40978 }
40979 
40980 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_trim(duk_hthread *thr) {
40981 	DUK_ASSERT_TOP(thr, 0);
40982 	(void) duk_push_this_coercible_to_string(thr);
40983 	duk_trim(thr, 0);
40984 	DUK_ASSERT_TOP(thr, 1);
40985 	return 1;
40986 }
40987 
40988 #if defined(DUK_USE_ES6)
40989 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_hthread *thr) {
40990 	duk_hstring *h_input;
40991 	duk_size_t input_blen;
40992 	duk_size_t result_len;
40993 	duk_int_t count_signed;
40994 	duk_uint_t count;
40995 	const duk_uint8_t *src;
40996 	duk_uint8_t *buf;
40997 	duk_uint8_t *p;
40998 	duk_double_t d;
40999 #if !defined(DUK_USE_PREFER_SIZE)
41000 	duk_size_t copy_size;
41001 	duk_uint8_t *p_end;
41002 #endif
41003 
41004 	DUK_ASSERT_TOP(thr, 1);
41005 	h_input = duk_push_this_coercible_to_string(thr);
41006 	DUK_ASSERT(h_input != NULL);
41007 	input_blen = DUK_HSTRING_GET_BYTELEN(h_input);
41008 
41009 	/* Count is ToNumber() coerced; +Infinity must be always rejected
41010 	 * (even if input string is zero length), as well as negative values
41011 	 * and -Infinity.  -Infinity doesn't require an explicit check
41012 	 * because duk_get_int() clamps it to DUK_INT_MIN which gets rejected
41013 	 * as a negative value (regardless of input string length).
41014 	 */
41015 	d = duk_to_number(thr, 0);
41016 	if (duk_double_is_posinf(d)) {
41017 		goto fail_range;
41018 	}
41019 	count_signed = duk_get_int(thr, 0);
41020 	if (count_signed < 0) {
41021 		goto fail_range;
41022 	}
41023 	count = (duk_uint_t) count_signed;
41024 
41025 	/* Overflow check for result length. */
41026 	result_len = count * input_blen;
41027 	if (count != 0 && result_len / count != input_blen) {
41028 		goto fail_range;
41029 	}
41030 
41031 	/* Temporary fixed buffer, later converted to string. */
41032 	buf = (duk_uint8_t *) duk_push_fixed_buffer_nozero(thr, result_len);
41033 	DUK_ASSERT(buf != NULL);
41034 	src = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
41035 	DUK_ASSERT(src != NULL);
41036 
41037 #if defined(DUK_USE_PREFER_SIZE)
41038 	p = buf;
41039 	while (count-- > 0) {
41040 		duk_memcpy((void *) p, (const void *) src, input_blen);  /* copy size may be zero, but pointers are valid */
41041 		p += input_blen;
41042 	}
41043 #else  /* DUK_USE_PREFER_SIZE */
41044 	/* Take advantage of already copied pieces to speed up the process
41045 	 * especially for small repeated strings.
41046 	 */
41047 	p = buf;
41048 	p_end = p + result_len;
41049 	copy_size = input_blen;
41050 	for (;;) {
41051 		duk_size_t remain = (duk_size_t) (p_end - p);
41052 		DUK_DDD(DUK_DDDPRINT("remain=%ld, copy_size=%ld, input_blen=%ld, result_len=%ld",
41053 		                     (long) remain, (long) copy_size, (long) input_blen,
41054 		                     (long) result_len));
41055 		if (remain <= copy_size) {
41056 			/* If result_len is zero, this case is taken and does
41057 			 * a zero size copy (with valid pointers).
41058 			 */
41059 			duk_memcpy((void *) p, (const void *) src, remain);
41060 			break;
41061 		} else {
41062 			duk_memcpy((void *) p, (const void *) src, copy_size);
41063 			p += copy_size;
41064 		}
41065 
41066 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
41067 		copy_size = (duk_size_t) (p - buf);
41068 	}
41069 #endif  /* DUK_USE_PREFER_SIZE */
41070 
41071 	/* XXX: It would be useful to be able to create a duk_hstring with
41072 	 * a certain byte size whose data area wasn't initialized and which
41073 	 * wasn't in the string table yet.  This would allow a string to be
41074 	 * constructed directly without a buffer temporary and when it was
41075 	 * finished, it could be injected into the string table.  Currently
41076 	 * this isn't possible because duk_hstrings are only tracked by the
41077 	 * intern table (they are not in heap_allocated).
41078 	 */
41079 
41080 	duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
41081 	return 1;
41082 
41083  fail_range:
41084 	DUK_DCERROR_RANGE_INVALID_ARGS(thr);
41085 }
41086 #endif  /* DUK_USE_ES6 */
41087 
41088 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_locale_compare(duk_hthread *thr) {
41089 	duk_hstring *h1;
41090 	duk_hstring *h2;
41091 	duk_size_t h1_len, h2_len, prefix_len;
41092 	duk_small_int_t ret = 0;
41093 	duk_small_int_t rc;
41094 
41095 	/* The current implementation of localeCompare() is simply a codepoint
41096 	 * by codepoint comparison, implemented with a simple string compare
41097 	 * because UTF-8 should preserve codepoint ordering (assuming valid
41098 	 * shortest UTF-8 encoding).
41099 	 *
41100 	 * The specification requires that the return value must be related
41101 	 * to the sort order: e.g. negative means that 'this' comes before
41102 	 * 'that' in sort order.  We assume an ascending sort order.
41103 	 */
41104 
41105 	/* XXX: could share code with duk_js_ops.c, duk_js_compare_helper */
41106 
41107 	h1 = duk_push_this_coercible_to_string(thr);
41108 	DUK_ASSERT(h1 != NULL);
41109 
41110 	h2 = duk_to_hstring(thr, 0);
41111 	DUK_ASSERT(h2 != NULL);
41112 
41113 	h1_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1);
41114 	h2_len = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2);
41115 	prefix_len = (h1_len <= h2_len ? h1_len : h2_len);
41116 
41117 	rc = (duk_small_int_t) duk_memcmp((const void *) DUK_HSTRING_GET_DATA(h1),
41118 	                                  (const void *) DUK_HSTRING_GET_DATA(h2),
41119 	                                  (size_t) prefix_len);
41120 
41121 	if (rc < 0) {
41122 		ret = -1;
41123 		goto done;
41124 	} else if (rc > 0) {
41125 		ret = 1;
41126 		goto done;
41127 	}
41128 
41129 	/* prefix matches, lengths matter now */
41130 	if (h1_len > h2_len) {
41131 		ret = 1;
41132 		goto done;
41133 	} else if (h1_len == h2_len) {
41134 		DUK_ASSERT(ret == 0);
41135 		goto done;
41136 	}
41137 	ret = -1;
41138 	goto done;
41139 
41140  done:
41141 	duk_push_int(thr, (duk_int_t) ret);
41142 	return 1;
41143 }
41144 
41145 #if defined(DUK_USE_ES6)
41146 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_startswith_endswith(duk_hthread *thr) {
41147 	duk_int_t magic;
41148 	duk_hstring *h;
41149 	duk_hstring *h_search;
41150 	duk_size_t blen_search;
41151 	const duk_uint8_t *p_cmp_start;
41152 	duk_bool_t result;
41153 
41154 	h = duk_push_this_coercible_to_string(thr);
41155 	DUK_ASSERT(h != NULL);
41156 
41157 	h_search = duk__str_tostring_notregexp(thr, 0);
41158 	DUK_ASSERT(h_search != NULL);
41159 
41160 	magic = duk_get_current_magic(thr);
41161 
41162 	p_cmp_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41163 	blen_search = DUK_HSTRING_GET_BYTELEN(h_search);
41164 
41165 	if (duk_is_undefined(thr, 1)) {
41166 		if (magic) {
41167 			p_cmp_start = p_cmp_start + DUK_HSTRING_GET_BYTELEN(h) - blen_search;
41168 		} else {
41169 			/* p_cmp_start already OK */
41170 		}
41171 	} else {
41172 		duk_int_t len;
41173 		duk_int_t pos;
41174 
41175 		DUK_ASSERT(DUK_HSTRING_MAX_BYTELEN <= DUK_INT_MAX);
41176 		len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41177 		pos = duk_to_int_clamped(thr, 1, 0, len);
41178 		DUK_ASSERT(pos >= 0 && pos <= len);
41179 
41180 		if (magic) {
41181 			p_cmp_start -= blen_search;  /* Conceptually subtracted last, but do already here. */
41182 		}
41183 		DUK_ASSERT(pos >= 0 && pos <= len);
41184 
41185 		p_cmp_start += duk_heap_strcache_offset_char2byte(thr, h, (duk_uint_fast32_t) pos);
41186 	}
41187 
41188 	/* The main comparison can be done using a memcmp() rather than
41189 	 * doing codepoint comparisons: for CESU-8 strings there is a
41190 	 * canonical representation for every codepoint.  But we do need
41191 	 * to deal with the char/byte offset translation to find the
41192 	 * comparison range.
41193 	 */
41194 
41195 	result = 0;
41196 	if (p_cmp_start >= DUK_HSTRING_GET_DATA(h) &&
41197 	    (duk_size_t) (p_cmp_start - (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h)) + blen_search <= DUK_HSTRING_GET_BYTELEN(h)) {
41198 		if (duk_memcmp((const void *) p_cmp_start,
41199 		               (const void *) DUK_HSTRING_GET_DATA(h_search),
41200 		               (size_t) blen_search) == 0) {
41201 			result = 1;
41202 		}
41203 	}
41204 
41205 	duk_push_boolean(thr, result);
41206 	return 1;
41207 }
41208 #endif  /* DUK_USE_ES6 */
41209 
41210 #if defined(DUK_USE_ES6)
41211 DUK_INTERNAL duk_ret_t duk_bi_string_prototype_includes(duk_hthread *thr) {
41212 	duk_hstring *h;
41213 	duk_hstring *h_search;
41214 	duk_int_t len;
41215 	duk_int_t pos;
41216 
41217 	h = duk_push_this_coercible_to_string(thr);
41218 	DUK_ASSERT(h != NULL);
41219 
41220 	h_search = duk__str_tostring_notregexp(thr, 0);
41221 	DUK_ASSERT(h_search != NULL);
41222 
41223 	len = (duk_int_t) DUK_HSTRING_GET_CHARLEN(h);
41224 	pos = duk_to_int_clamped(thr, 1, 0, len);
41225 	DUK_ASSERT(pos >= 0 && pos <= len);
41226 
41227 	pos = duk__str_search_shared(thr, h, h_search, pos, 0 /*backwards*/);
41228 	duk_push_boolean(thr, pos >= 0);
41229 	return 1;
41230 }
41231 #endif  /* DUK_USE_ES6 */
41232 #endif  /* DUK_USE_STRING_BUILTIN */
41233 #line 1 "duk_bi_symbol.c"
41234 /*
41235  *  Symbol built-in
41236  */
41237 
41238 /* #include duk_internal.h -> already included */
41239 
41240 #if defined(DUK_USE_SYMBOL_BUILTIN)
41241 
41242 /*
41243  *  Constructor
41244  */
41245 
41246 DUK_INTERNAL duk_ret_t duk_bi_symbol_constructor_shared(duk_hthread *thr) {
41247 	const duk_uint8_t *desc;
41248 	duk_size_t len;
41249 	duk_uint8_t *buf;
41250 	duk_uint8_t *p;
41251 	duk_int_t magic;
41252 
41253 	magic = duk_get_current_magic(thr);
41254 	if (duk_is_undefined(thr, 0) && (magic == 0)) {
41255 		/* Symbol() accepts undefined and empty string, but they are
41256 		 * treated differently.
41257 		 */
41258 		desc = NULL;
41259 		len = 0;
41260 	} else {
41261 		/* Symbol.for() coerces undefined to 'undefined' */
41262 		desc = (const duk_uint8_t *) duk_to_lstring(thr, 0, &len);
41263 	}
41264 
41265 	/* Maximum symbol data length:
41266 	 *   +1    initial byte (0x80 or 0x81)
41267 	 *   +len  description
41268 	 *   +1    0xff after description, before unique suffix
41269 	 *   +17   autogenerated unique suffix: 'ffffffff-ffffffff' is longest
41270 	 *   +1    0xff after unique suffix for symbols with undefined description
41271 	 */
41272 	buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, 1 + len + 1 + 17 + 1);
41273 	DUK_ASSERT(buf != NULL);
41274 	p = buf + 1;
41275 	DUK_ASSERT(desc != NULL || len == 0);  /* may be NULL if len is 0 */
41276 	duk_memcpy_unsafe((void *) p, (const void *) desc, len);
41277 	p += len;
41278 	if (magic == 0) {
41279 		/* Symbol(): create unique symbol.  Use two 32-bit values
41280 		 * to avoid dependency on 64-bit types and 64-bit integer
41281 		 * formatting (at least for now).
41282 		 */
41283 		if (++thr->heap->sym_counter[0] == 0) {
41284 			thr->heap->sym_counter[1]++;
41285 		}
41286 		p += DUK_SPRINTF((char *) p, "\xFF" "%lx-%lx",
41287 		                 (unsigned long) thr->heap->sym_counter[1],
41288 		                 (unsigned long) thr->heap->sym_counter[0]);
41289 		if (desc == NULL) {
41290 			/* Special case for 'undefined' description, trailing
41291 			 * 0xff distinguishes from empty string description,
41292 			 * but needs minimal special case handling elsewhere.
41293 			 */
41294 			*p++ = 0xff;
41295 		}
41296 		buf[0] = 0x81;
41297 	} else {
41298 		/* Symbol.for(): create a global symbol */
41299 		buf[0] = 0x80;
41300 	}
41301 
41302 	duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
41303 	DUK_DDD(DUK_DDDPRINT("created symbol: %!T", duk_get_tval(thr, -1)));
41304 	return 1;
41305 }
41306 
41307 DUK_LOCAL duk_hstring *duk__auto_unbox_symbol(duk_hthread *thr, duk_tval *tv_arg) {
41308 	duk_tval *tv;
41309 	duk_tval tv_val;
41310 	duk_hobject *h_obj;
41311 	duk_hstring *h_str;
41312 
41313 	DUK_ASSERT(tv_arg != NULL);
41314 
41315 	/* XXX: add internal helper: duk_auto_unbox_tval(thr, tv, mask); */
41316 	/* XXX: add internal helper: duk_auto_unbox(thr, tv, idx); */
41317 
41318 	tv = tv_arg;
41319 	if (DUK_TVAL_IS_OBJECT(tv)) {
41320 		h_obj = DUK_TVAL_GET_OBJECT(tv);
41321 		DUK_ASSERT(h_obj != NULL);
41322 		if (DUK_HOBJECT_GET_CLASS_NUMBER(h_obj) == DUK_HOBJECT_CLASS_SYMBOL) {
41323 			if (!duk_hobject_get_internal_value(thr->heap, h_obj, &tv_val)) {
41324 				return NULL;
41325 			}
41326 			tv = &tv_val;
41327 		} else {
41328 			return NULL;
41329 		}
41330 	}
41331 
41332 	if (!DUK_TVAL_IS_STRING(tv)) {
41333 		return NULL;
41334 	}
41335 	h_str = DUK_TVAL_GET_STRING(tv);
41336 	DUK_ASSERT(h_str != NULL);
41337 
41338 	/* Here symbol is more expected than not. */
41339 	if (DUK_UNLIKELY(!DUK_HSTRING_HAS_SYMBOL(h_str))) {
41340 		return NULL;
41341 	}
41342 
41343 	return h_str;
41344 }
41345 
41346 DUK_INTERNAL duk_ret_t duk_bi_symbol_tostring_shared(duk_hthread *thr) {
41347 	duk_hstring *h_str;
41348 
41349 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41350 	if (h_str == NULL) {
41351 		return DUK_RET_TYPE_ERROR;
41352 	}
41353 
41354 	if (duk_get_current_magic(thr) == 0) {
41355 		/* .toString() */
41356 		duk_push_symbol_descriptive_string(thr, h_str);
41357 	} else {
41358 		/* .valueOf() */
41359 		duk_push_hstring(thr, h_str);
41360 	}
41361 	return 1;
41362 }
41363 
41364 DUK_INTERNAL duk_ret_t duk_bi_symbol_key_for(duk_hthread *thr) {
41365 	duk_hstring *h;
41366 	const duk_uint8_t *p;
41367 
41368 	/* Argument must be a symbol but not checked here.  The initial byte
41369 	 * check will catch non-symbol strings.
41370 	 */
41371 	h = duk_require_hstring(thr, 0);
41372 	DUK_ASSERT(h != NULL);
41373 
41374 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
41375 	DUK_ASSERT(p != NULL);
41376 
41377 	/* Even for zero length strings there's at least one NUL byte so
41378 	 * we can safely check the initial byte.
41379 	 */
41380 	if (p[0] == 0x80) {
41381 		/* Global symbol, return its key (bytes just after the initial byte). */
41382 		duk_push_lstring(thr, (const char *) (p + 1), (duk_size_t) (DUK_HSTRING_GET_BYTELEN(h) - 1));
41383 		return 1;
41384 	} else if (p[0] == 0x81 || p[0] == 0x82 || p[0] == 0xff) {
41385 		/* Local symbol or hidden symbol, return undefined. */
41386 		return 0;
41387 	}
41388 
41389 	/* Covers normal strings and unknown initial bytes. */
41390 	return DUK_RET_TYPE_ERROR;
41391 }
41392 
41393 DUK_INTERNAL duk_ret_t duk_bi_symbol_toprimitive(duk_hthread *thr) {
41394 	duk_hstring *h_str;
41395 
41396 	h_str = duk__auto_unbox_symbol(thr, DUK_HTHREAD_THIS_PTR(thr));
41397 	if (h_str == NULL) {
41398 		return DUK_RET_TYPE_ERROR;
41399 	}
41400 	duk_push_hstring(thr, h_str);
41401 	return 1;
41402 }
41403 
41404 #endif  /* DUK_USE_SYMBOL_BUILTIN */
41405 #line 1 "duk_bi_thread.c"
41406 /*
41407  *  Thread builtins
41408  */
41409 
41410 /* #include duk_internal.h -> already included */
41411 
41412 /*
41413  *  Constructor
41414  */
41415 
41416 #if defined(DUK_USE_COROUTINE_SUPPORT)
41417 DUK_INTERNAL duk_ret_t duk_bi_thread_constructor(duk_hthread *thr) {
41418 	duk_hthread *new_thr;
41419 	duk_hobject *func;
41420 
41421 	/* Check that the argument is callable; this is not 100% because we
41422 	 * don't allow native functions to be a thread's initial function.
41423 	 * Resume will reject such functions in any case.
41424 	 */
41425 	/* XXX: need a duk_require_func_promote_lfunc() */
41426 	func = duk_require_hobject_promote_lfunc(thr, 0);
41427 	DUK_ASSERT(func != NULL);
41428 	duk_require_callable(thr, 0);
41429 
41430 	duk_push_thread(thr);
41431 	new_thr = (duk_hthread *) duk_known_hobject(thr, -1);
41432 	new_thr->state = DUK_HTHREAD_STATE_INACTIVE;
41433 
41434 	/* push initial function call to new thread stack; this is
41435 	 * picked up by resume().
41436 	 */
41437 	duk_push_hobject(new_thr, func);
41438 
41439 	return 1;  /* return thread */
41440 }
41441 #endif
41442 
41443 /*
41444  *  Resume a thread.
41445  *
41446  *  The thread must be in resumable state, either (a) new thread which hasn't
41447  *  yet started, or (b) a thread which has previously yielded.  This method
41448  *  must be called from an ECMAScript function.
41449  *
41450  *  Args:
41451  *    - thread
41452  *    - value
41453  *    - isError (defaults to false)
41454  *
41455  *  Note: yield and resume handling is currently asymmetric.
41456  */
41457 
41458 #if defined(DUK_USE_COROUTINE_SUPPORT)
41459 DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_hthread *ctx) {
41460 	duk_hthread *thr = (duk_hthread *) ctx;
41461 	duk_hthread *thr_resume;
41462 	duk_hobject *caller_func;
41463 	duk_small_uint_t is_error;
41464 
41465 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.resume(): thread=%!T, value=%!T, is_error=%!T",
41466 	                     (duk_tval *) duk_get_tval(thr, 0),
41467 	                     (duk_tval *) duk_get_tval(thr, 1),
41468 	                     (duk_tval *) duk_get_tval(thr, 2)));
41469 
41470 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41471 	DUK_ASSERT(thr->heap->curr_thread == thr);
41472 
41473 	thr_resume = duk_require_hthread(thr, 0);
41474 	DUK_ASSERT(duk_get_top(thr) == 3);
41475 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41476 	DUK_ASSERT(duk_get_top(thr) == 2);
41477 
41478 	/* [ thread value ] */
41479 
41480 	/*
41481 	 *  Thread state and calling context checks
41482 	 */
41483 
41484 	if (thr->callstack_top < 2) {
41485 		DUK_DD(DUK_DDPRINT("resume state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.resume)"));
41486 		goto state_error;
41487 	}
41488 	DUK_ASSERT(thr->callstack_curr != NULL);
41489 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41490 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41491 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41492 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41493 
41494 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41495 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41496 		DUK_DD(DUK_DDPRINT("resume state invalid: caller must be ECMAScript code"));
41497 		goto state_error;
41498 	}
41499 
41500 	/* Note: there is no requirement that: 'thr->callstack_preventcount == 1'
41501 	 * like for yield.
41502 	 */
41503 
41504 	if (thr_resume->state != DUK_HTHREAD_STATE_INACTIVE &&
41505 	    thr_resume->state != DUK_HTHREAD_STATE_YIELDED) {
41506 		DUK_DD(DUK_DDPRINT("resume state invalid: target thread must be INACTIVE or YIELDED"));
41507 		goto state_error;
41508 	}
41509 
41510 	DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE ||
41511 	           thr_resume->state == DUK_HTHREAD_STATE_YIELDED);
41512 
41513 	/* Further state-dependent pre-checks */
41514 
41515 	if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41516 		/* no pre-checks now, assume a previous yield() has left things in
41517 		 * tip-top shape (longjmp handler will assert for these).
41518 		 */
41519 	} else {
41520 		duk_hobject *h_fun;
41521 
41522 		DUK_ASSERT(thr_resume->state == DUK_HTHREAD_STATE_INACTIVE);
41523 
41524 		/* The initial function must be an ECMAScript function (but
41525 		 * can be bound).  We must make sure of that before we longjmp
41526 		 * because an error in the RESUME handler call processing will
41527 		 * not be handled very cleanly.
41528 		 */
41529 		if ((thr_resume->callstack_top != 0) ||
41530 		    (thr_resume->valstack_top - thr_resume->valstack != 1)) {
41531 			goto state_error;
41532 		}
41533 
41534 		duk_push_tval(thr, DUK_GET_TVAL_NEGIDX(thr_resume, -1));
41535 		duk_resolve_nonbound_function(thr);
41536 		h_fun = duk_require_hobject(thr, -1);  /* reject lightfuncs on purpose */
41537 		if (!DUK_HOBJECT_IS_CALLABLE(h_fun) || !DUK_HOBJECT_IS_COMPFUNC(h_fun)) {
41538 			goto state_error;
41539 		}
41540 		duk_pop(thr);
41541 	}
41542 
41543 	/*
41544 	 *  The error object has been augmented with a traceback and other
41545 	 *  info from its creation point -- usually another thread.  The
41546 	 *  error handler is called here right before throwing, but it also
41547 	 *  runs in the resumer's thread.  It might be nice to get a traceback
41548 	 *  from the resumee but this is not the case now.
41549 	 */
41550 
41551 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41552 	if (is_error) {
41553 		DUK_ASSERT_TOP(thr, 2);  /* value (error) is at stack top */
41554 		duk_err_augment_error_throw(thr);  /* in resumer's context */
41555 	}
41556 #endif
41557 
41558 #if defined(DUK_USE_DEBUG)
41559 	if (is_error) {
41560 		DUK_DDD(DUK_DDDPRINT("RESUME ERROR: thread=%!T, value=%!T",
41561 		                     (duk_tval *) duk_get_tval(thr, 0),
41562 		                     (duk_tval *) duk_get_tval(thr, 1)));
41563 	} else if (thr_resume->state == DUK_HTHREAD_STATE_YIELDED) {
41564 		DUK_DDD(DUK_DDDPRINT("RESUME NORMAL: thread=%!T, value=%!T",
41565 		                     (duk_tval *) duk_get_tval(thr, 0),
41566 		                     (duk_tval *) duk_get_tval(thr, 1)));
41567 	} else {
41568 		DUK_DDD(DUK_DDDPRINT("RESUME INITIAL: thread=%!T, value=%!T",
41569 		                     (duk_tval *) duk_get_tval(thr, 0),
41570 		                     (duk_tval *) duk_get_tval(thr, 1)));
41571 	}
41572 #endif
41573 
41574 	thr->heap->lj.type = DUK_LJ_TYPE_RESUME;
41575 
41576 	/* lj value2: thread */
41577 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41578 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value2, &thr->valstack_bottom[0]);  /* side effects */
41579 
41580 	/* lj value1: value */
41581 	DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
41582 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]);  /* side effects */
41583 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41584 
41585 	thr->heap->lj.iserror = is_error;
41586 
41587 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41588 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41589 	DUK_UNREACHABLE();
41590 	/* Never here, fall through to error (from compiler point of view). */
41591 
41592  state_error:
41593 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41594 }
41595 #endif
41596 
41597 /*
41598  *  Yield the current thread.
41599  *
41600  *  The thread must be in yieldable state: it must have a resumer, and there
41601  *  must not be any yield-preventing calls (native calls and constructor calls,
41602  *  currently) in the thread's call stack (otherwise a resume would not be
41603  *  possible later).  This method must be called from an ECMAScript function.
41604  *
41605  *  Args:
41606  *    - value
41607  *    - isError (defaults to false)
41608  *
41609  *  Note: yield and resume handling is currently asymmetric.
41610  */
41611 
41612 #if defined(DUK_USE_COROUTINE_SUPPORT)
41613 DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_hthread *thr) {
41614 	duk_hobject *caller_func;
41615 	duk_small_uint_t is_error;
41616 
41617 	DUK_DDD(DUK_DDDPRINT("Duktape.Thread.yield(): value=%!T, is_error=%!T",
41618 	                     (duk_tval *) duk_get_tval(thr, 0),
41619 	                     (duk_tval *) duk_get_tval(thr, 1)));
41620 
41621 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
41622 	DUK_ASSERT(thr->heap->curr_thread == thr);
41623 
41624 	DUK_ASSERT(duk_get_top(thr) == 2);
41625 	is_error = (duk_small_uint_t) duk_to_boolean_top_pop(thr);
41626 	DUK_ASSERT(duk_get_top(thr) == 1);
41627 
41628 	/* [ value ] */
41629 
41630 	/*
41631 	 *  Thread state and calling context checks
41632 	 */
41633 
41634 	if (!thr->resumer) {
41635 		DUK_DD(DUK_DDPRINT("yield state invalid: current thread must have a resumer"));
41636 		goto state_error;
41637 	}
41638 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
41639 
41640 	if (thr->callstack_top < 2) {
41641 		DUK_DD(DUK_DDPRINT("yield state invalid: callstack should contain at least 2 entries (caller and Duktape.Thread.yield)"));
41642 		goto state_error;
41643 	}
41644 	DUK_ASSERT(thr->callstack_curr != NULL);
41645 	DUK_ASSERT(thr->callstack_curr->parent != NULL);
41646 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);  /* us */
41647 	DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
41648 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL);  /* caller */
41649 
41650 	caller_func = DUK_ACT_GET_FUNC(thr->callstack_curr->parent);
41651 	if (!DUK_HOBJECT_IS_COMPFUNC(caller_func)) {
41652 		DUK_DD(DUK_DDPRINT("yield state invalid: caller must be ECMAScript code"));
41653 		goto state_error;
41654 	}
41655 
41656 	DUK_ASSERT(thr->callstack_preventcount >= 1);  /* should never be zero, because we (Duktape.Thread.yield) are on the stack */
41657 	if (thr->callstack_preventcount != 1) {
41658 		/* Note: the only yield-preventing call is Duktape.Thread.yield(), hence check for 1, not 0 */
41659 		DUK_DD(DUK_DDPRINT("yield state invalid: there must be no yield-preventing calls in current thread callstack (preventcount is %ld)",
41660 		                   (long) thr->callstack_preventcount));
41661 		goto state_error;
41662 	}
41663 
41664 	/*
41665 	 *  The error object has been augmented with a traceback and other
41666 	 *  info from its creation point -- usually the current thread.
41667 	 *  The error handler, however, is called right before throwing
41668 	 *  and runs in the yielder's thread.
41669 	 */
41670 
41671 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
41672 	if (is_error) {
41673 		DUK_ASSERT_TOP(thr, 1);  /* value (error) is at stack top */
41674 		duk_err_augment_error_throw(thr);  /* in yielder's context */
41675 	}
41676 #endif
41677 
41678 #if defined(DUK_USE_DEBUG)
41679 	if (is_error) {
41680 		DUK_DDD(DUK_DDDPRINT("YIELD ERROR: value=%!T",
41681 		                     (duk_tval *) duk_get_tval(thr, 0)));
41682 	} else {
41683 		DUK_DDD(DUK_DDDPRINT("YIELD NORMAL: value=%!T",
41684 		                     (duk_tval *) duk_get_tval(thr, 0)));
41685 	}
41686 #endif
41687 
41688 	/*
41689 	 *  Process yield
41690 	 *
41691 	 *  After longjmp(), processing continues in bytecode executor longjmp
41692 	 *  handler, which will e.g. update thr->resumer to NULL.
41693 	 */
41694 
41695 	thr->heap->lj.type = DUK_LJ_TYPE_YIELD;
41696 
41697 	/* lj value1: value */
41698 	DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
41699 	DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]);  /* side effects */
41700 	DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
41701 
41702 	thr->heap->lj.iserror = is_error;
41703 
41704 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* call is from executor, so we know we have a jmpbuf */
41705 	duk_err_longjmp(thr);  /* execution resumes in bytecode executor */
41706 	DUK_UNREACHABLE();
41707 	/* Never here, fall through to error (from compiler point of view). */
41708 
41709  state_error:
41710 	DUK_DCERROR_TYPE_INVALID_STATE(thr);
41711 }
41712 #endif
41713 
41714 #if defined(DUK_USE_COROUTINE_SUPPORT)
41715 DUK_INTERNAL duk_ret_t duk_bi_thread_current(duk_hthread *thr) {
41716 	duk_push_current_thread(thr);
41717 	return 1;
41718 }
41719 #endif
41720 #line 1 "duk_bi_thrower.c"
41721 /*
41722  *  Type error thrower, E5 Section 13.2.3.
41723  */
41724 
41725 /* #include duk_internal.h -> already included */
41726 
41727 DUK_INTERNAL duk_ret_t duk_bi_type_error_thrower(duk_hthread *thr) {
41728 	DUK_DCERROR_TYPE_INVALID_ARGS(thr);
41729 }
41730 #line 1 "duk_debug_fixedbuffer.c"
41731 /*
41732  *  Fixed buffer helper useful for debugging, requires no allocation
41733  *  which is critical for debugging.
41734  */
41735 
41736 /* #include duk_internal.h -> already included */
41737 
41738 #if defined(DUK_USE_DEBUG)
41739 
41740 DUK_INTERNAL void duk_fb_put_bytes(duk_fixedbuffer *fb, const duk_uint8_t *buffer, duk_size_t length) {
41741 	duk_size_t avail;
41742 	duk_size_t copylen;
41743 
41744 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41745 	if (length > avail) {
41746 		copylen = avail;
41747 		fb->truncated = 1;
41748 	} else {
41749 		copylen = length;
41750 	}
41751 	duk_memcpy_unsafe(fb->buffer + fb->offset, buffer, copylen);
41752 	fb->offset += copylen;
41753 }
41754 
41755 DUK_INTERNAL void duk_fb_put_byte(duk_fixedbuffer *fb, duk_uint8_t x) {
41756 	duk_fb_put_bytes(fb, (const duk_uint8_t *) &x, 1);
41757 }
41758 
41759 DUK_INTERNAL void duk_fb_put_cstring(duk_fixedbuffer *fb, const char *x) {
41760 	duk_fb_put_bytes(fb, (const duk_uint8_t *) x, (duk_size_t) DUK_STRLEN(x));
41761 }
41762 
41763 DUK_INTERNAL void duk_fb_sprintf(duk_fixedbuffer *fb, const char *fmt, ...) {
41764 	duk_size_t avail;
41765 	va_list ap;
41766 
41767 	va_start(ap, fmt);
41768 	avail = (fb->offset >= fb->length ? (duk_size_t) 0 : (duk_size_t) (fb->length - fb->offset));
41769 	if (avail > 0) {
41770 		duk_int_t res = (duk_int_t) DUK_VSNPRINTF((char *) (fb->buffer + fb->offset), avail, fmt, ap);
41771 		if (res < 0) {
41772 			/* error */
41773 		} else if ((duk_size_t) res >= avail) {
41774 			/* (maybe) truncated */
41775 			fb->offset += avail;
41776 			if ((duk_size_t) res > avail) {
41777 				/* actual chars dropped (not just NUL term) */
41778 				fb->truncated = 1;
41779 			}
41780 		} else {
41781 			/* normal */
41782 			fb->offset += (duk_size_t) res;
41783 		}
41784 	}
41785 	va_end(ap);
41786 }
41787 
41788 DUK_INTERNAL void duk_fb_put_funcptr(duk_fixedbuffer *fb, duk_uint8_t *fptr, duk_size_t fptr_size) {
41789 	char buf[64+1];
41790 	duk_debug_format_funcptr(buf, sizeof(buf), fptr, fptr_size);
41791 	buf[sizeof(buf) - 1] = (char) 0;
41792 	duk_fb_put_cstring(fb, buf);
41793 }
41794 
41795 DUK_INTERNAL duk_bool_t duk_fb_is_full(duk_fixedbuffer *fb) {
41796 	return (fb->offset >= fb->length);
41797 }
41798 
41799 #endif  /* DUK_USE_DEBUG */
41800 #line 1 "duk_debug_vsnprintf.c"
41801 /*
41802  *  Custom formatter for debug printing, allowing Duktape specific data
41803  *  structures (such as tagged values and heap objects) to be printed with
41804  *  a nice format string.  Because debug printing should not affect execution
41805  *  state, formatting here must be independent of execution (see implications
41806  *  below) and must not allocate memory.
41807  *
41808  *  Custom format tags begin with a '%!' to safely distinguish them from
41809  *  standard format tags.  The following conversions are supported:
41810  *
41811  *     %!T    tagged value (duk_tval *)
41812  *     %!O    heap object (duk_heaphdr *)
41813  *     %!I    decoded bytecode instruction
41814  *     %!C    bytecode instruction opcode name (arg is long)
41815  *
41816  *  Everything is serialized in a JSON-like manner.  The default depth is one
41817  *  level, internal prototype is not followed, and internal properties are not
41818  *  serialized.  The following modifiers change this behavior:
41819  *
41820  *     @      print pointers
41821  *     #      print binary representations (where applicable)
41822  *     d      deep traversal of own properties (not prototype)
41823  *     p      follow prototype chain (useless without 'd')
41824  *     i      include internal properties (other than prototype)
41825  *     x      hexdump buffers
41826  *     h      heavy formatting
41827  *
41828  *  For instance, the following serializes objects recursively, but does not
41829  *  follow the prototype chain nor print internal properties: "%!dO".
41830  *
41831  *  Notes:
41832  *
41833  *    * Standard snprintf return value semantics seem to vary.  This
41834  *      implementation returns the number of bytes it actually wrote
41835  *      (excluding the null terminator).  If retval == buffer size,
41836  *      output was truncated (except for corner cases).
41837  *
41838  *    * Output format is intentionally different from ECMAScript
41839  *      formatting requirements, as formatting here serves debugging
41840  *      of internals.
41841  *
41842  *    * Depth checking (and updating) is done in each type printer
41843  *      separately, to allow them to call each other freely.
41844  *
41845  *    * Some pathological structures might take ages to print (e.g.
41846  *      self recursion with 100 properties pointing to the object
41847  *      itself).  To guard against these, each printer also checks
41848  *      whether the output buffer is full; if so, early exit.
41849  *
41850  *    * Reference loops are detected using a loop stack.
41851  */
41852 
41853 /* #include duk_internal.h -> already included */
41854 
41855 #if defined(DUK_USE_DEBUG)
41856 
41857 /* #include stdio.h -> already included */
41858 /* #include stdarg.h -> already included */
41859 #include <string.h>
41860 
41861 /* list of conversion specifiers that terminate a format tag;
41862  * this is unfortunately guesswork.
41863  */
41864 #define DUK__ALLOWED_STANDARD_SPECIFIERS  "diouxXeEfFgGaAcsCSpnm"
41865 
41866 /* maximum length of standard format tag that we support */
41867 #define DUK__MAX_FORMAT_TAG_LENGTH  32
41868 
41869 /* heapobj recursion depth when deep printing is selected */
41870 #define DUK__DEEP_DEPTH_LIMIT  8
41871 
41872 /* maximum recursion depth for loop detection stacks */
41873 #define DUK__LOOP_STACK_DEPTH  256
41874 
41875 /* must match bytecode defines now; build autogenerate? */
41876 DUK_LOCAL const char * const duk__bc_optab[256] = {
41877 	"LDREG", "STREG", "JUMP", "LDCONST", "LDINT", "LDINTX", "LDTHIS", "LDUNDEF",
41878 	"LDNULL", "LDTRUE", "LDFALSE", "GETVAR", "BNOT", "LNOT", "UNM", "UNP",
41879 	"EQ_RR", "EQ_CR", "EQ_RC", "EQ_CC", "NEQ_RR", "NEQ_CR", "NEQ_RC", "NEQ_CC",
41880 	"SEQ_RR", "SEQ_CR", "SEQ_RC", "SEQ_CC", "SNEQ_RR", "SNEQ_CR", "SNEQ_RC", "SNEQ_CC",
41881 
41882 	"GT_RR", "GT_CR", "GT_RC", "GT_CC", "GE_RR", "GE_CR", "GE_RC", "GE_CC",
41883 	"LT_RR", "LT_CR", "LT_RC", "LT_CC", "LE_RR", "LE_CR", "LE_RC", "LE_CC",
41884 	"IFTRUE_R", "IFTRUE_C", "IFFALSE_R", "IFFALSE_C", "ADD_RR", "ADD_CR", "ADD_RC", "ADD_CC",
41885 	"SUB_RR", "SUB_CR", "SUB_RC", "SUB_CC", "MUL_RR", "MUL_CR", "MUL_RC", "MUL_CC",
41886 
41887 	"DIV_RR", "DIV_CR", "DIV_RC", "DIV_CC", "MOD_RR", "MOD_CR", "MOD_RC", "MOD_CC",
41888 	"EXP_RR", "EXP_CR", "EXP_RC", "EXP_CC", "BAND_RR", "BAND_CR", "BAND_RC", "BAND_CC",
41889 	"BOR_RR", "BOR_CR", "BOR_RC", "BOR_CC", "BXOR_RR", "BXOR_CR", "BXOR_RC", "BXOR_CC",
41890 	"BASL_RR", "BASL_CR", "BASL_RC", "BASL_CC", "BLSR_RR", "BLSR_CR", "BLSR_RC", "BLSR_CC",
41891 
41892 	"BASR_RR", "BASR_CR", "BASR_RC", "BASR_CC", "INSTOF_RR", "INSTOF_CR", "INSTOF_RC", "INSTOF_CC",
41893 	"IN_RR", "IN_CR", "IN_RC", "IN_CC", "GETPROP_RR", "GETPROP_CR", "GETPROP_RC", "GETPROP_CC",
41894 	"PUTPROP_RR", "PUTPROP_CR", "PUTPROP_RC", "PUTPROP_CC", "DELPROP_RR", "DELPROP_CR", "DELPROP_RC", "DELPROP_CC",
41895 	"PREINCR", "PREDECR", "POSTINCR", "POSTDECR", "PREINCV", "PREDECV", "POSTINCV", "POSTDECV",
41896 
41897 	"PREINCP_RR", "PREINCP_CR", "PREINCP_RC", "PREINCP_CC", "PREDECP_RR", "PREDECP_CR", "PREDECP_RC", "PREDECP_CC",
41898 	"POSTINCP_RR", "POSTINCP_CR", "POSTINCP_RC", "POSTINCP_CC", "POSTDECP_RR", "POSTDECP_CR", "POSTDECP_RC", "POSTDECP_CC",
41899 	"DECLVAR_RR", "DECLVAR_CR", "DECLVAR_RC", "DECLVAR_CC", "REGEXP_RR", "REGEXP_RC", "REGEXP_CR", "REGEXP_CC",
41900 	"CLOSURE", "TYPEOF", "TYPEOFID", "PUTVAR", "DELVAR", "RETREG", "RETUNDEF", "RETCONST",
41901 
41902 	"RETCONSTN", "LABEL", "ENDLABEL", "BREAK", "CONTINUE", "TRYCATCH", "ENDTRY", "ENDCATCH",
41903 	"ENDFIN", "THROW", "INVLHS", "CSREG", "CSVAR_RR", "CSVAR_CR", "CSVAR_RC", "CSVAR_CC",
41904 	"CALL0", "CALL1", "CALL2", "CALL3", "CALL4", "CALL5", "CALL6", "CALL7",
41905 	"CALL8", "CALL9", "CALL10", "CALL11", "CALL12", "CALL13", "CALL14", "CALL15",
41906 
41907 	"NEWOBJ", "NEWARR", "MPUTOBJ", "MPUTOBJI", "INITSET", "INITGET", "MPUTARR", "MPUTARRI",
41908 	"SETALEN", "INITENUM", "NEXTENUM", "NEWTARGET", "DEBUGGER", "NOP", "INVALID", "UNUSED207",
41909 	"GETPROPC_RR", "GETPROPC_CR", "GETPROPC_RC", "GETPROPC_CC", "UNUSED212", "UNUSED213", "UNUSED214", "UNUSED215",
41910 	"UNUSED216", "UNUSED217", "UNUSED218", "UNUSED219", "UNUSED220", "UNUSED221", "UNUSED222", "UNUSED223",
41911 
41912 	"UNUSED224", "UNUSED225", "UNUSED226", "UNUSED227", "UNUSED228", "UNUSED229", "UNUSED230", "UNUSED231",
41913 	"UNUSED232", "UNUSED233", "UNUSED234", "UNUSED235", "UNUSED236", "UNUSED237", "UNUSED238", "UNUSED239",
41914 	"UNUSED240", "UNUSED241", "UNUSED242", "UNUSED243", "UNUSED244", "UNUSED245", "UNUSED246", "UNUSED247",
41915 	"UNUSED248", "UNUSED249", "UNUSED250", "UNUSED251", "UNUSED252", "UNUSED253", "UNUSED254", "UNUSED255"
41916 };
41917 
41918 typedef struct duk__dprint_state duk__dprint_state;
41919 struct duk__dprint_state {
41920 	duk_fixedbuffer *fb;
41921 
41922 	/* loop_stack_index could be perhaps be replaced by 'depth', but it's nice
41923 	 * to not couple these two mechanisms unnecessarily.
41924 	 */
41925 	duk_hobject *loop_stack[DUK__LOOP_STACK_DEPTH];
41926 	duk_int_t loop_stack_index;
41927 	duk_int_t loop_stack_limit;
41928 
41929 	duk_int_t depth;
41930 	duk_int_t depth_limit;
41931 
41932 	duk_bool_t pointer;
41933 	duk_bool_t heavy;
41934 	duk_bool_t binary;
41935 	duk_bool_t follow_proto;
41936 	duk_bool_t internal;
41937 	duk_bool_t hexdump;
41938 };
41939 
41940 /* helpers */
41941 DUK_LOCAL_DECL void duk__print_hstring(duk__dprint_state *st, duk_hstring *k, duk_bool_t quotes);
41942 DUK_LOCAL_DECL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h);
41943 DUK_LOCAL_DECL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h);
41944 DUK_LOCAL_DECL void duk__print_tval(duk__dprint_state *st, duk_tval *tv);
41945 DUK_LOCAL_DECL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins);
41946 DUK_LOCAL_DECL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
41947 DUK_LOCAL_DECL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h);
41948 DUK_LOCAL_DECL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h);
41949 
41950 DUK_LOCAL void duk__print_shared_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
41951 	duk_fixedbuffer *fb = st->fb;
41952 
41953 	if (st->heavy) {
41954 		duk_fb_sprintf(fb, "(%p)", (void *) h);
41955 	}
41956 
41957 	if (!h) {
41958 		return;
41959 	}
41960 
41961 	if (st->binary) {
41962 		duk_size_t i;
41963 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
41964 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
41965 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
41966 		}
41967 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
41968 	}
41969 
41970 #if defined(DUK_USE_REFERENCE_COUNTING)  /* currently implicitly also DUK_USE_DOUBLE_LINKED_HEAP */
41971 	if (st->heavy) {
41972 		duk_fb_sprintf(fb, "[h_next=%p,h_prev=%p,h_refcount=%lu,h_flags=%08lx,type=%ld,"
41973 		               "reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
41974 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
41975 		               (void *) DUK_HEAPHDR_GET_PREV(NULL, h),
41976 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(h),
41977 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
41978 		               (long) DUK_HEAPHDR_GET_TYPE(h),
41979 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
41980 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
41981 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
41982 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
41983 	}
41984 #else
41985 	if (st->heavy) {
41986 		duk_fb_sprintf(fb, "[h_next=%p,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
41987 		               (void *) DUK_HEAPHDR_GET_NEXT(NULL, h),
41988 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS(h),
41989 		               (long) DUK_HEAPHDR_GET_TYPE(h),
41990 		               (long) (DUK_HEAPHDR_HAS_REACHABLE(h) ? 1 : 0),
41991 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT(h) ? 1 : 0),
41992 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE(h) ? 1 : 0),
41993 		               (long) (DUK_HEAPHDR_HAS_FINALIZED(h) ? 1 : 0));
41994 	}
41995 #endif
41996 }
41997 
41998 DUK_LOCAL void duk__print_shared_heaphdr_string(duk__dprint_state *st, duk_heaphdr_string *h) {
41999 	duk_fixedbuffer *fb = st->fb;
42000 
42001 	if (st->heavy) {
42002 		duk_fb_sprintf(fb, "(%p)", (void *) h);
42003 	}
42004 
42005 	if (!h) {
42006 		return;
42007 	}
42008 
42009 	if (st->binary) {
42010 		duk_size_t i;
42011 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42012 		for (i = 0; i < (duk_size_t) sizeof(*h); i++) {
42013 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)h)[i]);
42014 		}
42015 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42016 	}
42017 
42018 #if defined(DUK_USE_REFERENCE_COUNTING)
42019 	if (st->heavy) {
42020 		duk_fb_sprintf(fb, "[h_refcount=%lu,h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42021 		               (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h),
42022 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42023 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42024 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42025 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42026 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42027 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42028 	}
42029 #else
42030 	if (st->heavy) {
42031 		duk_fb_sprintf(fb, "[h_flags=%08lx,type=%ld,reachable=%ld,temproot=%ld,finalizable=%ld,finalized=%ld]",
42032 		               (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) h),
42033 		               (long) DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h),
42034 		               (long) (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h) ? 1 : 0),
42035 		               (long) (DUK_HEAPHDR_HAS_TEMPROOT((duk_heaphdr *) h) ? 1 : 0),
42036 		               (long) (DUK_HEAPHDR_HAS_FINALIZABLE((duk_heaphdr *) h) ? 1 : 0),
42037 		               (long) (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h) ? 1 : 0));
42038 	}
42039 #endif
42040 }
42041 
42042 DUK_LOCAL void duk__print_hstring(duk__dprint_state *st, duk_hstring *h, duk_bool_t quotes) {
42043 	duk_fixedbuffer *fb = st->fb;
42044 	const duk_uint8_t *p;
42045 	const duk_uint8_t *p_end;
42046 
42047 	/* terminal type: no depth check */
42048 
42049 	if (duk_fb_is_full(fb)) {
42050 		return;
42051 	}
42052 
42053 	duk__print_shared_heaphdr_string(st, &h->hdr);
42054 
42055 	if (!h) {
42056 		duk_fb_put_cstring(fb, "NULL");
42057 		return;
42058 	}
42059 
42060 	p = DUK_HSTRING_GET_DATA(h);
42061 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
42062 
42063 	if (p_end > p && p[0] == DUK_ASC_UNDERSCORE) {
42064 		/* If property key begins with underscore, encode it with
42065 		 * forced quotes (e.g. "_Foo") to distinguish it from encoded
42066 		 * internal properties (e.g. \x82Bar -> _Bar).
42067 		 */
42068 		quotes = 1;
42069 	}
42070 
42071 	if (quotes) {
42072 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42073 	}
42074 	while (p < p_end) {
42075 		duk_uint8_t ch = *p++;
42076 
42077 		/* two special escapes: '\' and '"', other printables as is */
42078 		if (ch == '\\') {
42079 			duk_fb_sprintf(fb, "\\\\");
42080 		} else if (ch == '"') {
42081 			duk_fb_sprintf(fb, "\\\"");
42082 		} else if (ch >= 0x20 && ch <= 0x7e) {
42083 			duk_fb_put_byte(fb, ch);
42084 		} else if (ch == 0x82 && !quotes) {
42085 			/* encode \x82Bar as _Bar if no quotes are
42086 			 * applied, this is for readable internal keys.
42087 			 */
42088 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_UNDERSCORE);
42089 		} else {
42090 			duk_fb_sprintf(fb, "\\x%02lx", (unsigned long) ch);
42091 		}
42092 	}
42093 	if (quotes) {
42094 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_DOUBLEQUOTE);
42095 	}
42096 #if defined(DUK_USE_REFERENCE_COUNTING)
42097 	/* XXX: limit to quoted strings only, to save keys from being cluttered? */
42098 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42099 #endif
42100 }
42101 
42102 #define DUK__COMMA()  do { \
42103 		if (first) { \
42104 			first = 0; \
42105 		} else { \
42106 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA); \
42107 		} \
42108 	} while (0)
42109 
42110 DUK_LOCAL void duk__print_hobject(duk__dprint_state *st, duk_hobject *h) {
42111 	duk_fixedbuffer *fb = st->fb;
42112 	duk_uint_fast32_t i;
42113 	duk_tval *tv;
42114 	duk_hstring *key;
42115 	duk_bool_t first = 1;
42116 	const char *brace1 = "{";
42117 	const char *brace2 = "}";
42118 	duk_bool_t pushed_loopstack = 0;
42119 
42120 	if (duk_fb_is_full(fb)) {
42121 		return;
42122 	}
42123 
42124 	duk__print_shared_heaphdr(st, &h->hdr);
42125 
42126 	if (h && DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42127 		brace1 = "[";
42128 		brace2 = "]";
42129 	}
42130 
42131 	if (!h) {
42132 		duk_fb_put_cstring(fb, "NULL");
42133 		goto finished;
42134 	}
42135 
42136 	if (st->depth >= st->depth_limit) {
42137 		const char *subtype = "generic";
42138 
42139 		if (DUK_HOBJECT_IS_COMPFUNC(h)) {
42140 			subtype = "compfunc";
42141 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
42142 			subtype = "natfunc";
42143 		} else if (DUK_HOBJECT_IS_THREAD(h)) {
42144 			subtype = "thread";
42145 		} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42146 			subtype = "bufobj";
42147 		} else if (DUK_HOBJECT_IS_ARRAY(h)) {
42148 			subtype = "array";
42149 		}
42150 		duk_fb_sprintf(fb, "%sobject/%s %p%s", (const char *) brace1, subtype, (void *) h, (const char *) brace2);
42151 		return;
42152 	}
42153 
42154 	for (i = 0; i < (duk_uint_fast32_t) st->loop_stack_index; i++) {
42155 		if (st->loop_stack[i] == h) {
42156 			duk_fb_sprintf(fb, "%sLOOP:%p%s", (const char *) brace1, (void *) h, (const char *) brace2);
42157 			return;
42158 		}
42159 	}
42160 
42161 	/* after this, return paths should 'goto finished' for decrement */
42162 	st->depth++;
42163 
42164 	if (st->loop_stack_index >= st->loop_stack_limit) {
42165 		duk_fb_sprintf(fb, "%sOUT-OF-LOOP-STACK%s", (const char *) brace1, (const char *) brace2);
42166 		goto finished;
42167 	}
42168 	st->loop_stack[st->loop_stack_index++] = h;
42169 	pushed_loopstack = 1;
42170 
42171 	/*
42172 	 *  Notation: double underscore used for internal properties which are not
42173 	 *  stored in the property allocation (e.g. '__valstack').
42174 	 */
42175 
42176 	duk_fb_put_cstring(fb, brace1);
42177 
42178 	if (DUK_HOBJECT_GET_PROPS(NULL, h)) {
42179 		duk_uint32_t a_limit;
42180 
42181 		a_limit = DUK_HOBJECT_GET_ASIZE(h);
42182 		if (st->internal) {
42183 			/* dump all allocated entries, unused entries print as 'unused',
42184 			 * note that these may extend beyond current 'length' and look
42185 			 * a bit funny.
42186 			 */
42187 		} else {
42188 			/* leave out trailing 'unused' elements */
42189 			while (a_limit > 0) {
42190 				tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, a_limit - 1);
42191 				if (!DUK_TVAL_IS_UNUSED(tv)) {
42192 					break;
42193 				}
42194 				a_limit--;
42195 			}
42196 		}
42197 
42198 		for (i = 0; i < a_limit; i++) {
42199 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(NULL, h, i);
42200 			DUK__COMMA();
42201 			duk__print_tval(st, tv);
42202 		}
42203 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(h); i++) {
42204 			key = DUK_HOBJECT_E_GET_KEY(NULL, h, i);
42205 			if (!key) {
42206 				continue;
42207 			}
42208 			if (!st->internal && DUK_HSTRING_HAS_HIDDEN(key)) {
42209 				continue;
42210 			}
42211 			DUK__COMMA();
42212 			duk__print_hstring(st, key, 0);
42213 			duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COLON);
42214 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(NULL, h, i)) {
42215 				duk_fb_sprintf(fb, "[get:%p,set:%p]",
42216 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.get,
42217 				               (void *) DUK_HOBJECT_E_GET_VALUE(NULL, h, i).a.set);
42218 			} else {
42219 				tv = &DUK_HOBJECT_E_GET_VALUE(NULL, h, i).v;
42220 				duk__print_tval(st, tv);
42221 			}
42222 			if (st->heavy) {
42223 				duk_fb_sprintf(fb, "<%02lx>", (unsigned long) DUK_HOBJECT_E_GET_FLAGS(NULL, h, i));
42224 			}
42225 		}
42226 	}
42227 	if (st->internal) {
42228 		if (DUK_HOBJECT_IS_ARRAY(h)) {
42229 			DUK__COMMA(); duk_fb_sprintf(fb, "__array:true");
42230 		}
42231 		if (DUK_HOBJECT_HAS_EXTENSIBLE(h)) {
42232 			DUK__COMMA(); duk_fb_sprintf(fb, "__extensible:true");
42233 		}
42234 		if (DUK_HOBJECT_HAS_CONSTRUCTABLE(h)) {
42235 			DUK__COMMA(); duk_fb_sprintf(fb, "__constructable:true");
42236 		}
42237 		if (DUK_HOBJECT_HAS_BOUNDFUNC(h)) {
42238 			DUK__COMMA(); duk_fb_sprintf(fb, "__boundfunc:true");
42239 		}
42240 		if (DUK_HOBJECT_HAS_COMPFUNC(h)) {
42241 			DUK__COMMA(); duk_fb_sprintf(fb, "__compfunc:true");
42242 		}
42243 		if (DUK_HOBJECT_HAS_NATFUNC(h)) {
42244 			DUK__COMMA(); duk_fb_sprintf(fb, "__natfunc:true");
42245 		}
42246 		if (DUK_HOBJECT_HAS_BUFOBJ(h)) {
42247 			DUK__COMMA(); duk_fb_sprintf(fb, "__bufobj:true");
42248 		}
42249 		if (DUK_HOBJECT_IS_THREAD(h)) {
42250 			DUK__COMMA(); duk_fb_sprintf(fb, "__thread:true");
42251 		}
42252 		if (DUK_HOBJECT_HAS_ARRAY_PART(h)) {
42253 			DUK__COMMA(); duk_fb_sprintf(fb, "__array_part:true");
42254 		}
42255 		if (DUK_HOBJECT_HAS_STRICT(h)) {
42256 			DUK__COMMA(); duk_fb_sprintf(fb, "__strict:true");
42257 		}
42258 		if (DUK_HOBJECT_HAS_NOTAIL(h)) {
42259 			DUK__COMMA(); duk_fb_sprintf(fb, "__notail:true");
42260 		}
42261 		if (DUK_HOBJECT_HAS_NEWENV(h)) {
42262 			DUK__COMMA(); duk_fb_sprintf(fb, "__newenv:true");
42263 		}
42264 		if (DUK_HOBJECT_HAS_NAMEBINDING(h)) {
42265 			DUK__COMMA(); duk_fb_sprintf(fb, "__namebinding:true");
42266 		}
42267 		if (DUK_HOBJECT_HAS_CREATEARGS(h)) {
42268 			DUK__COMMA(); duk_fb_sprintf(fb, "__createargs:true");
42269 		}
42270 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(h)) {
42271 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_array:true");
42272 		}
42273 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(h)) {
42274 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_stringobj:true");
42275 		}
42276 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h)) {
42277 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_arguments:true");
42278 		}
42279 		if (DUK_HOBJECT_IS_BUFOBJ(h)) {
42280 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_bufobj:true");
42281 		}
42282 		if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(h)) {
42283 			DUK__COMMA(); duk_fb_sprintf(fb, "__exotic_proxyobj:true");
42284 		}
42285 	}
42286 
42287 	if (st->internal && DUK_HOBJECT_IS_ARRAY(h)) {
42288 		duk_harray *a = (duk_harray *) h;
42289 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) a->length);
42290 		DUK__COMMA(); duk_fb_sprintf(fb, "__length_nonwritable:%ld", (long) a->length_nonwritable);
42291 	} else if (st->internal && DUK_HOBJECT_IS_COMPFUNC(h)) {
42292 		duk_hcompfunc *f = (duk_hcompfunc *) h;
42293 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42294 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42295 		DUK__COMMA(); duk_fb_put_cstring(fb, "__lexenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_LEXENV(NULL, f));
42296 		DUK__COMMA(); duk_fb_put_cstring(fb, "__varenv:"); duk__print_hobject(st, DUK_HCOMPFUNC_GET_VARENV(NULL, f));
42297 		DUK__COMMA(); duk_fb_sprintf(fb, "__nregs:%ld", (long) f->nregs);
42298 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42299 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42300 		DUK__COMMA(); duk_fb_sprintf(fb, "__start_line:%ld", (long) f->start_line);
42301 		DUK__COMMA(); duk_fb_sprintf(fb, "__end_line:%ld", (long) f->end_line);
42302 #endif
42303 		DUK__COMMA(); duk_fb_put_cstring(fb, "__data:");
42304 		duk__print_hbuffer(st, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(NULL, f));
42305 	} else if (st->internal && DUK_HOBJECT_IS_NATFUNC(h)) {
42306 		duk_hnatfunc *f = (duk_hnatfunc *) h;
42307 		DUK__COMMA(); duk_fb_sprintf(fb, "__func:");
42308 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &f->func, sizeof(f->func));
42309 		DUK__COMMA(); duk_fb_sprintf(fb, "__nargs:%ld", (long) f->nargs);
42310 		DUK__COMMA(); duk_fb_sprintf(fb, "__magic:%ld", (long) f->magic);
42311 	} else if (st->internal && DUK_HOBJECT_IS_DECENV(h)) {
42312 		duk_hdecenv *e = (duk_hdecenv *) h;
42313 		DUK__COMMA(); duk_fb_sprintf(fb, "__thread:"); duk__print_hobject(st, (duk_hobject *) e->thread);
42314 		DUK__COMMA(); duk_fb_sprintf(fb, "__varmap:"); duk__print_hobject(st, (duk_hobject *) e->varmap);
42315 		DUK__COMMA(); duk_fb_sprintf(fb, "__regbase_byteoff:%ld", (long) e->regbase_byteoff);
42316 	} else if (st->internal && DUK_HOBJECT_IS_OBJENV(h)) {
42317 		duk_hobjenv *e = (duk_hobjenv *) h;
42318 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:"); duk__print_hobject(st, (duk_hobject *) e->target);
42319 		DUK__COMMA(); duk_fb_sprintf(fb, "__has_this:%ld", (long) e->has_this);
42320 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
42321 	} else if (st->internal && DUK_HOBJECT_IS_BUFOBJ(h)) {
42322 		duk_hbufobj *b = (duk_hbufobj *) h;
42323 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf:");
42324 		duk__print_hbuffer(st, (duk_hbuffer *) b->buf);
42325 		DUK__COMMA(); duk_fb_sprintf(fb, "__buf_prop:");
42326 		duk__print_hobject(st, (duk_hobject *) b->buf_prop);
42327 		DUK__COMMA(); duk_fb_sprintf(fb, "__offset:%ld", (long) b->offset);
42328 		DUK__COMMA(); duk_fb_sprintf(fb, "__length:%ld", (long) b->length);
42329 		DUK__COMMA(); duk_fb_sprintf(fb, "__shift:%ld", (long) b->shift);
42330 		DUK__COMMA(); duk_fb_sprintf(fb, "__elemtype:%ld", (long) b->elem_type);
42331 #endif
42332 	} else if (st->internal && DUK_HOBJECT_IS_PROXY(h)) {
42333 		duk_hproxy *p = (duk_hproxy *) h;
42334 		DUK__COMMA(); duk_fb_sprintf(fb, "__target:");
42335 		duk__print_hobject(st, p->target);
42336 		DUK__COMMA(); duk_fb_sprintf(fb, "__handler:");
42337 		duk__print_hobject(st, p->handler);
42338 	} else if (st->internal && DUK_HOBJECT_IS_THREAD(h)) {
42339 		duk_hthread *t = (duk_hthread *) h;
42340 		DUK__COMMA(); duk_fb_sprintf(fb, "__ptr_curr_pc:%p", (void *) t->ptr_curr_pc);
42341 		DUK__COMMA(); duk_fb_sprintf(fb, "__heap:%p", (void *) t->heap);
42342 		DUK__COMMA(); duk_fb_sprintf(fb, "__strict:%ld", (long) t->strict);
42343 		DUK__COMMA(); duk_fb_sprintf(fb, "__state:%ld", (long) t->state);
42344 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused1:%ld", (long) t->unused1);
42345 		DUK__COMMA(); duk_fb_sprintf(fb, "__unused2:%ld", (long) t->unused2);
42346 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack:%p", (void *) t->valstack);
42347 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_end:%p/%ld", (void *) t->valstack_end, (long) (t->valstack_end - t->valstack));
42348 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_alloc_end:%p/%ld", (void *) t->valstack_alloc_end, (long) (t->valstack_alloc_end - t->valstack));
42349 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_bottom:%p/%ld", (void *) t->valstack_bottom, (long) (t->valstack_bottom - t->valstack));
42350 		DUK__COMMA(); duk_fb_sprintf(fb, "__valstack_top:%p/%ld", (void *) t->valstack_top, (long) (t->valstack_top - t->valstack));
42351 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_curr:%p", (void *) t->callstack_curr);
42352 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_top:%ld", (long) t->callstack_top);
42353 		DUK__COMMA(); duk_fb_sprintf(fb, "__callstack_preventcount:%ld", (long) t->callstack_preventcount);
42354 		DUK__COMMA(); duk_fb_sprintf(fb, "__resumer:"); duk__print_hobject(st, (duk_hobject *) t->resumer);
42355 		DUK__COMMA(); duk_fb_sprintf(fb, "__compile_ctx:%p", (void *) t->compile_ctx);
42356 #if defined(DUK_USE_INTERRUPT_COUNTER)
42357 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_counter:%ld", (long) t->interrupt_counter);
42358 		DUK__COMMA(); duk_fb_sprintf(fb, "__interrupt_init:%ld", (long) t->interrupt_init);
42359 #endif
42360 
42361 		/* XXX: print built-ins array? */
42362 
42363 	}
42364 #if defined(DUK_USE_REFERENCE_COUNTING)
42365 	if (st->internal) {
42366 		DUK__COMMA(); duk_fb_sprintf(fb, "__refcount:%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h));
42367 	}
42368 #endif
42369 	if (st->internal) {
42370 		DUK__COMMA(); duk_fb_sprintf(fb, "__class:%ld", (long) DUK_HOBJECT_GET_CLASS_NUMBER(h));
42371 	}
42372 
42373 	DUK__COMMA(); duk_fb_sprintf(fb, "__heapptr:%p", (void *) h);  /* own pointer */
42374 
42375 	/* prototype should be last, for readability */
42376 	if (DUK_HOBJECT_GET_PROTOTYPE(NULL, h)) {
42377 		if (st->follow_proto) {
42378 			DUK__COMMA(); duk_fb_put_cstring(fb, "__prototype:"); duk__print_hobject(st, DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42379 		} else {
42380 			DUK__COMMA(); duk_fb_sprintf(fb, "__prototype:%p", (void *) DUK_HOBJECT_GET_PROTOTYPE(NULL, h));
42381 		}
42382 	}
42383 
42384 	duk_fb_put_cstring(fb, brace2);
42385 
42386 #if defined(DUK_USE_HOBJECT_HASH_PART)
42387 	if (st->heavy && DUK_HOBJECT_GET_HSIZE(h) > 0) {
42388 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42389 		for (i = 0; i < DUK_HOBJECT_GET_HSIZE(h); i++) {
42390 			duk_uint_t h_idx = DUK_HOBJECT_H_GET_INDEX(NULL, h, i);
42391 			if (i > 0) {
42392 				duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_COMMA);
42393 			}
42394 			if (h_idx == DUK_HOBJECT_HASHIDX_UNUSED) {
42395 				duk_fb_sprintf(fb, "u");
42396 			} else if (h_idx == DUK_HOBJECT_HASHIDX_DELETED) {
42397 				duk_fb_sprintf(fb, "d");
42398 			} else {
42399 				duk_fb_sprintf(fb, "%ld", (long) h_idx);
42400 			}
42401 		}
42402 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42403 	}
42404 #endif
42405 
42406  finished:
42407 	st->depth--;
42408 	if (pushed_loopstack) {
42409 		st->loop_stack_index--;
42410 		st->loop_stack[st->loop_stack_index] = NULL;
42411 	}
42412 }
42413 
42414 DUK_LOCAL void duk__print_hbuffer(duk__dprint_state *st, duk_hbuffer *h) {
42415 	duk_fixedbuffer *fb = st->fb;
42416 	duk_size_t i, n;
42417 	duk_uint8_t *p;
42418 
42419 	if (duk_fb_is_full(fb)) {
42420 		return;
42421 	}
42422 
42423 	/* terminal type: no depth check */
42424 
42425 	if (!h) {
42426 		duk_fb_put_cstring(fb, "NULL");
42427 		return;
42428 	}
42429 
42430 	if (DUK_HBUFFER_HAS_DYNAMIC(h)) {
42431 		if (DUK_HBUFFER_HAS_EXTERNAL(h)) {
42432 			duk_hbuffer_external *g = (duk_hbuffer_external *) h;
42433 			duk_fb_sprintf(fb, "buffer:external:%p:%ld",
42434 			               (void *) DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(NULL, g),
42435 			               (long) DUK_HBUFFER_EXTERNAL_GET_SIZE(g));
42436 		} else {
42437 			duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
42438 			duk_fb_sprintf(fb, "buffer:dynamic:%p:%ld",
42439 			               (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(NULL, g),
42440 			               (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(g));
42441 		}
42442 	} else {
42443 		duk_fb_sprintf(fb, "buffer:fixed:%ld", (long) DUK_HBUFFER_GET_SIZE(h));
42444 	}
42445 
42446 #if defined(DUK_USE_REFERENCE_COUNTING)
42447 	duk_fb_sprintf(fb, "/%lu", (unsigned long) DUK_HEAPHDR_GET_REFCOUNT(&h->hdr));
42448 #endif
42449 
42450 	if (st->hexdump) {
42451 		duk_fb_sprintf(fb, "=[");
42452 		n = DUK_HBUFFER_GET_SIZE(h);
42453 		p = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(NULL, h);
42454 		for (i = 0; i < n; i++) {
42455 			duk_fb_sprintf(fb, "%02lx", (unsigned long) p[i]);
42456 		}
42457 		duk_fb_sprintf(fb, "]");
42458 	}
42459 }
42460 
42461 DUK_LOCAL void duk__print_heaphdr(duk__dprint_state *st, duk_heaphdr *h) {
42462 	duk_fixedbuffer *fb = st->fb;
42463 
42464 	if (duk_fb_is_full(fb)) {
42465 		return;
42466 	}
42467 
42468 	if (!h) {
42469 		duk_fb_put_cstring(fb, "NULL");
42470 		return;
42471 	}
42472 
42473 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
42474 	case DUK_HTYPE_STRING:
42475 		duk__print_hstring(st, (duk_hstring *) h, 1);
42476 		break;
42477 	case DUK_HTYPE_OBJECT:
42478 		duk__print_hobject(st, (duk_hobject *) h);
42479 		break;
42480 	case DUK_HTYPE_BUFFER:
42481 		duk__print_hbuffer(st, (duk_hbuffer *) h);
42482 		break;
42483 	default:
42484 		duk_fb_sprintf(fb, "[unknown htype %ld]", (long) DUK_HEAPHDR_GET_TYPE(h));
42485 		break;
42486 	}
42487 }
42488 
42489 DUK_LOCAL void duk__print_tval(duk__dprint_state *st, duk_tval *tv) {
42490 	duk_fixedbuffer *fb = st->fb;
42491 
42492 	if (duk_fb_is_full(fb)) {
42493 		return;
42494 	}
42495 
42496 	/* depth check is done when printing an actual type */
42497 
42498 	if (st->heavy) {
42499 		duk_fb_sprintf(fb, "(%p)", (void *) tv);
42500 	}
42501 
42502 	if (!tv) {
42503 		duk_fb_put_cstring(fb, "NULL");
42504 		return;
42505 	}
42506 
42507 	if (st->binary) {
42508 		duk_size_t i;
42509 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LBRACKET);
42510 		for (i = 0; i < (duk_size_t) sizeof(*tv); i++) {
42511 			duk_fb_sprintf(fb, "%02lx", (unsigned long) ((duk_uint8_t *)tv)[i]);
42512 		}
42513 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RBRACKET);
42514 	}
42515 
42516 	if (st->heavy) {
42517 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_LANGLE);
42518 	}
42519 	switch (DUK_TVAL_GET_TAG(tv)) {
42520 	case DUK_TAG_UNDEFINED: {
42521 		duk_fb_put_cstring(fb, "undefined");
42522 		break;
42523 	}
42524 	case DUK_TAG_UNUSED: {
42525 		duk_fb_put_cstring(fb, "unused");
42526 		break;
42527 	}
42528 	case DUK_TAG_NULL: {
42529 		duk_fb_put_cstring(fb, "null");
42530 		break;
42531 	}
42532 	case DUK_TAG_BOOLEAN: {
42533 		duk_fb_put_cstring(fb, DUK_TVAL_GET_BOOLEAN(tv) ? "true" : "false");
42534 		break;
42535 	}
42536 	case DUK_TAG_STRING: {
42537 		/* Note: string is a terminal heap object, so no depth check here */
42538 		duk__print_hstring(st, DUK_TVAL_GET_STRING(tv), 1);
42539 		break;
42540 	}
42541 	case DUK_TAG_OBJECT: {
42542 		duk__print_hobject(st, DUK_TVAL_GET_OBJECT(tv));
42543 		break;
42544 	}
42545 	case DUK_TAG_BUFFER: {
42546 		duk__print_hbuffer(st, DUK_TVAL_GET_BUFFER(tv));
42547 		break;
42548 	}
42549 	case DUK_TAG_POINTER: {
42550 		duk_fb_sprintf(fb, "pointer:%p", (void *) DUK_TVAL_GET_POINTER(tv));
42551 		break;
42552 	}
42553 	case DUK_TAG_LIGHTFUNC: {
42554 		duk_c_function func;
42555 		duk_small_uint_t lf_flags;
42556 
42557 		DUK_TVAL_GET_LIGHTFUNC(tv, func, lf_flags);
42558 		duk_fb_sprintf(fb, "lightfunc:");
42559 		duk_fb_put_funcptr(fb, (duk_uint8_t *) &func, sizeof(func));
42560 		duk_fb_sprintf(fb, ":%04lx", (long) lf_flags);
42561 		break;
42562 	}
42563 #if defined(DUK_USE_FASTINT)
42564 	case DUK_TAG_FASTINT:
42565 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42566 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42567 		duk_fb_sprintf(fb, "%.18g_F", (double) DUK_TVAL_GET_NUMBER(tv));
42568 		break;
42569 #endif
42570 	default: {
42571 		/* IEEE double is approximately 16 decimal digits; print a couple extra */
42572 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
42573 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
42574 		duk_fb_sprintf(fb, "%.18g", (double) DUK_TVAL_GET_NUMBER(tv));
42575 		break;
42576 	}
42577 	}
42578 	if (st->heavy) {
42579 		duk_fb_put_byte(fb, (duk_uint8_t) DUK_ASC_RANGLE);
42580 	}
42581 }
42582 
42583 DUK_LOCAL void duk__print_instr(duk__dprint_state *st, duk_instr_t ins) {
42584 	duk_fixedbuffer *fb = st->fb;
42585 	duk_small_int_t op;
42586 	const char *op_name;
42587 
42588 	op = (duk_small_int_t) DUK_DEC_OP(ins);
42589 	op_name = duk__bc_optab[op];
42590 
42591 	/* XXX: option to fix opcode length so it lines up nicely */
42592 
42593 	if (op == DUK_OP_JUMP) {
42594 		duk_int_t diff1 = (duk_int_t) (DUK_DEC_ABC(ins) - DUK_BC_JUMP_BIAS);  /* from next pc */
42595 		duk_int_t diff2 = diff1 + 1;                                          /* from curr pc */
42596 
42597 		duk_fb_sprintf(fb, "%s %ld (to pc%c%ld)",
42598 		               (const char *) op_name, (long) diff1,
42599 		               (int) (diff2 >= 0 ? '+' : '-'),  /* char format: use int */
42600 		               (long) (diff2 >= 0 ? diff2 : -diff2));
42601 	} else {
42602 		duk_fb_sprintf(fb, "%s %ld, %ld, %ld",
42603 		               (const char *) op_name, (long) DUK_DEC_A(ins),
42604 		               (long) DUK_DEC_B(ins), (long) DUK_DEC_C(ins));
42605 	}
42606 }
42607 
42608 DUK_LOCAL void duk__print_opcode(duk__dprint_state *st, duk_small_int_t opcode) {
42609 	duk_fixedbuffer *fb = st->fb;
42610 
42611 	if (opcode < DUK_BC_OP_MIN || opcode > DUK_BC_OP_MAX) {
42612 		duk_fb_sprintf(fb, "?(%ld)", (long) opcode);
42613 	} else {
42614 		duk_fb_sprintf(fb, "%s", (const char *) duk__bc_optab[opcode]);
42615 	}
42616 }
42617 
42618 DUK_INTERNAL duk_int_t duk_debug_vsnprintf(char *str, duk_size_t size, const char *format, va_list ap) {
42619 	duk_fixedbuffer fb;
42620 	const char *p = format;
42621 	const char *p_end = p + DUK_STRLEN(format);
42622 	duk_int_t retval;
42623 
42624 	duk_memzero(&fb, sizeof(fb));
42625 	fb.buffer = (duk_uint8_t *) str;
42626 	fb.length = size;
42627 	fb.offset = 0;
42628 	fb.truncated = 0;
42629 
42630 	while (p < p_end) {
42631 		char ch = *p++;
42632 		const char *p_begfmt = NULL;
42633 		duk_bool_t got_exclamation = 0;
42634 		duk_bool_t got_long = 0;  /* %lf, %ld etc */
42635 		duk__dprint_state st;
42636 
42637 		if (ch != DUK_ASC_PERCENT) {
42638 			duk_fb_put_byte(&fb, (duk_uint8_t) ch);
42639 			continue;
42640 		}
42641 
42642 		/*
42643 		 *  Format tag parsing.  Since we don't understand all the
42644 		 *  possible format tags allowed, we just scan for a terminating
42645 		 *  specifier and keep track of relevant modifiers that we do
42646 		 *  understand.  See man 3 printf.
42647 		 */
42648 
42649 		duk_memzero(&st, sizeof(st));
42650 		st.fb = &fb;
42651 		st.depth = 0;
42652 		st.depth_limit = 1;
42653 		st.loop_stack_index = 0;
42654 		st.loop_stack_limit = DUK__LOOP_STACK_DEPTH;
42655 
42656 		p_begfmt = p - 1;
42657 		while (p < p_end) {
42658 			ch = *p++;
42659 
42660 			if (ch == DUK_ASC_STAR) {
42661 				/* unsupported: would consume multiple args */
42662 				goto format_error;
42663 			} else if (ch == DUK_ASC_PERCENT) {
42664 				duk_fb_put_byte(&fb, (duk_uint8_t) DUK_ASC_PERCENT);
42665 				break;
42666 			} else if (ch == DUK_ASC_EXCLAMATION) {
42667 				got_exclamation = 1;
42668 			} else if (!got_exclamation && ch == DUK_ASC_LC_L) {
42669 				got_long = 1;
42670 			} else if (got_exclamation && ch == DUK_ASC_LC_D) {
42671 				st.depth_limit = DUK__DEEP_DEPTH_LIMIT;
42672 			} else if (got_exclamation && ch == DUK_ASC_LC_P) {
42673 				st.follow_proto = 1;
42674 			} else if (got_exclamation && ch == DUK_ASC_LC_I) {
42675 				st.internal = 1;
42676 			} else if (got_exclamation && ch == DUK_ASC_LC_X) {
42677 				st.hexdump = 1;
42678 			} else if (got_exclamation && ch == DUK_ASC_LC_H) {
42679 				st.heavy = 1;
42680 			} else if (got_exclamation && ch == DUK_ASC_ATSIGN) {
42681 				st.pointer = 1;
42682 			} else if (got_exclamation && ch == DUK_ASC_HASH) {
42683 				st.binary = 1;
42684 			} else if (got_exclamation && ch == DUK_ASC_UC_T) {
42685 				duk_tval *t = va_arg(ap, duk_tval *);
42686 				if (st.pointer && !st.heavy) {
42687 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42688 				}
42689 				duk__print_tval(&st, t);
42690 				break;
42691 			} else if (got_exclamation && ch == DUK_ASC_UC_O) {
42692 				duk_heaphdr *t = va_arg(ap, duk_heaphdr *);
42693 				if (st.pointer && !st.heavy) {
42694 					duk_fb_sprintf(&fb, "(%p)", (void *) t);
42695 				}
42696 				duk__print_heaphdr(&st, t);
42697 				break;
42698 			} else if (got_exclamation && ch == DUK_ASC_UC_I) {
42699 				duk_instr_t t = va_arg(ap, duk_instr_t);
42700 				duk__print_instr(&st, t);
42701 				break;
42702 			} else if (got_exclamation && ch == DUK_ASC_UC_C) {
42703 				long t = va_arg(ap, long);
42704 				duk__print_opcode(&st, (duk_small_int_t) t);
42705 				break;
42706 			} else if (!got_exclamation && strchr(DUK__ALLOWED_STANDARD_SPECIFIERS, (int) ch)) {
42707 				char fmtbuf[DUK__MAX_FORMAT_TAG_LENGTH];
42708 				duk_size_t fmtlen;
42709 
42710 				DUK_ASSERT(p >= p_begfmt);
42711 				fmtlen = (duk_size_t) (p - p_begfmt);
42712 				if (fmtlen >= sizeof(fmtbuf)) {
42713 					/* format is too large, abort */
42714 					goto format_error;
42715 				}
42716 				duk_memzero(fmtbuf, sizeof(fmtbuf));
42717 				duk_memcpy(fmtbuf, p_begfmt, fmtlen);
42718 
42719 				/* assume exactly 1 arg, which is why '*' is forbidden; arg size still
42720 				 * depends on type though.
42721 				 */
42722 
42723 				if (ch == DUK_ASC_LC_F || ch == DUK_ASC_LC_G || ch == DUK_ASC_LC_E) {
42724 					/* %f and %lf both consume a 'long' */
42725 					double arg = va_arg(ap, double);
42726 					duk_fb_sprintf(&fb, fmtbuf, arg);
42727 				} else if (ch == DUK_ASC_LC_D && got_long) {
42728 					/* %ld */
42729 					long arg = va_arg(ap, long);
42730 					duk_fb_sprintf(&fb, fmtbuf, arg);
42731 				} else if (ch == DUK_ASC_LC_D) {
42732 					/* %d; only 16 bits are guaranteed */
42733 					int arg = va_arg(ap, int);
42734 					duk_fb_sprintf(&fb, fmtbuf, arg);
42735 				} else if (ch == DUK_ASC_LC_U && got_long) {
42736 					/* %lu */
42737 					unsigned long arg = va_arg(ap, unsigned long);
42738 					duk_fb_sprintf(&fb, fmtbuf, arg);
42739 				} else if (ch == DUK_ASC_LC_U) {
42740 					/* %u; only 16 bits are guaranteed */
42741 					unsigned int arg = va_arg(ap, unsigned int);
42742 					duk_fb_sprintf(&fb, fmtbuf, arg);
42743 				} else if (ch == DUK_ASC_LC_X && got_long) {
42744 					/* %lx */
42745 					unsigned long arg = va_arg(ap, unsigned long);
42746 					duk_fb_sprintf(&fb, fmtbuf, arg);
42747 				} else if (ch == DUK_ASC_LC_X) {
42748 					/* %x; only 16 bits are guaranteed */
42749 					unsigned int arg = va_arg(ap, unsigned int);
42750 					duk_fb_sprintf(&fb, fmtbuf, arg);
42751 				} else if (ch == DUK_ASC_LC_S) {
42752 					/* %s */
42753 					const char *arg = va_arg(ap, const char *);
42754 					if (arg == NULL) {
42755 						/* '%s' and NULL is not portable, so special case
42756 						 * it for debug printing.
42757 						 */
42758 						duk_fb_sprintf(&fb, "NULL");
42759 					} else {
42760 						duk_fb_sprintf(&fb, fmtbuf, arg);
42761 					}
42762 				} else if (ch == DUK_ASC_LC_P) {
42763 					/* %p */
42764 					void *arg = va_arg(ap, void *);
42765 					if (arg == NULL) {
42766 						/* '%p' and NULL is portable, but special case it
42767 						 * anyway to get a standard NULL marker in logs.
42768 						 */
42769 						duk_fb_sprintf(&fb, "NULL");
42770 					} else {
42771 						duk_fb_sprintf(&fb, fmtbuf, arg);
42772 					}
42773 				} else if (ch == DUK_ASC_LC_C) {
42774 					/* '%c', passed concretely as int */
42775 					int arg = va_arg(ap, int);
42776 					duk_fb_sprintf(&fb, fmtbuf, arg);
42777 				} else {
42778 					/* Should not happen. */
42779 					duk_fb_sprintf(&fb, "INVALID-FORMAT(%s)", (const char *) fmtbuf);
42780 				}
42781 				break;
42782 			} else {
42783 				/* ignore */
42784 			}
42785 		}
42786 	}
42787 	goto done;
42788 
42789  format_error:
42790 	duk_fb_put_cstring(&fb, "FMTERR");
42791 	/* fall through */
42792 
42793  done:
42794 	retval = (duk_int_t) fb.offset;
42795 	duk_fb_put_byte(&fb, (duk_uint8_t) 0);
42796 
42797 	/* return total chars written excluding terminator */
42798 	return retval;
42799 }
42800 
42801 #if 0  /*unused*/
42802 DUK_INTERNAL duk_int_t duk_debug_snprintf(char *str, duk_size_t size, const char *format, ...) {
42803 	duk_int_t retval;
42804 	va_list ap;
42805 	va_start(ap, format);
42806 	retval = duk_debug_vsnprintf(str, size, format, ap);
42807 	va_end(ap);
42808 	return retval;
42809 }
42810 #endif
42811 
42812 /* Formatting function pointers is tricky: there is no standard pointer for
42813  * function pointers and the size of a function pointer may depend on the
42814  * specific pointer type.  This helper formats a function pointer based on
42815  * its memory layout to get something useful on most platforms.
42816  */
42817 DUK_INTERNAL void duk_debug_format_funcptr(char *buf, duk_size_t buf_size, duk_uint8_t *fptr, duk_size_t fptr_size) {
42818 	duk_size_t i;
42819 	duk_uint8_t *p = (duk_uint8_t *) buf;
42820 	duk_uint8_t *p_end = (duk_uint8_t *) (buf + buf_size - 1);
42821 
42822 	DUK_ASSERT(buf != NULL);
42823 	duk_memzero(buf, buf_size);
42824 
42825 	for (i = 0; i < fptr_size; i++) {
42826 		duk_int_t left = (duk_int_t) (p_end - p);
42827 		duk_uint8_t ch;
42828 		if (left <= 0) {
42829 			break;
42830 		}
42831 
42832 		/* Quite approximate but should be useful for little and big endian. */
42833 #if defined(DUK_USE_INTEGER_BE)
42834 		ch = fptr[i];
42835 #else
42836 		ch = fptr[fptr_size - 1 - i];
42837 #endif
42838 		p += DUK_SNPRINTF((char *) p, (duk_size_t) left, "%02lx", (unsigned long) ch);
42839 	}
42840 }
42841 
42842 #endif  /* DUK_USE_DEBUG */
42843 
42844 /* automatic undefs */
42845 #undef DUK__ALLOWED_STANDARD_SPECIFIERS
42846 #undef DUK__COMMA
42847 #undef DUK__DEEP_DEPTH_LIMIT
42848 #undef DUK__LOOP_STACK_DEPTH
42849 #undef DUK__MAX_FORMAT_TAG_LENGTH
42850 #line 1 "duk_debugger.c"
42851 /*
42852  *  Duktape debugger
42853  */
42854 
42855 /* #include duk_internal.h -> already included */
42856 
42857 #if defined(DUK_USE_DEBUGGER_SUPPORT)
42858 
42859 /*
42860  *  Assert helpers
42861  */
42862 
42863 #if defined(DUK_USE_ASSERTIONS)
42864 #define DUK__DBG_TPORT_ENTER() do { \
42865 		DUK_ASSERT(heap->dbg_calling_transport == 0); \
42866 		heap->dbg_calling_transport = 1; \
42867 	} while (0)
42868 #define DUK__DBG_TPORT_EXIT() do { \
42869 		DUK_ASSERT(heap->dbg_calling_transport == 1); \
42870 		heap->dbg_calling_transport = 0; \
42871 	} while (0)
42872 #else
42873 #define DUK__DBG_TPORT_ENTER() do {} while (0)
42874 #define DUK__DBG_TPORT_EXIT() do {} while (0)
42875 #endif
42876 
42877 /*
42878  *  Helper structs
42879  */
42880 
42881 typedef union {
42882 	void *p;
42883 	duk_uint_t b[1];
42884 	/* Use b[] to access the size of the union, which is strictly not
42885 	 * correct.  Can't use fixed size unless there's feature detection
42886 	 * for pointer byte size.
42887 	 */
42888 } duk__ptr_union;
42889 
42890 /*
42891  *  Detach handling
42892  */
42893 
42894 #define DUK__SET_CONN_BROKEN(thr,reason) do { \
42895 		/* For now shared handler is fine. */ \
42896 		duk__debug_do_detach1((thr)->heap, (reason)); \
42897 	} while (0)
42898 
42899 DUK_LOCAL void duk__debug_do_detach1(duk_heap *heap, duk_int_t reason) {
42900 	/* Can be called multiple times with no harm.  Mark the transport
42901 	 * bad (dbg_read_cb == NULL) and clear state except for the detached
42902 	 * callback and the udata field.  The detached callback is delayed
42903 	 * to the message loop so that it can be called between messages;
42904 	 * this avoids corner cases related to immediate debugger reattach
42905 	 * inside the detached callback.
42906 	 */
42907 
42908 	if (heap->dbg_detaching) {
42909 		DUK_D(DUK_DPRINT("debugger already detaching, ignore detach1"));
42910 		return;
42911 	}
42912 
42913 	DUK_D(DUK_DPRINT("debugger transport detaching, marking transport broken"));
42914 
42915 	heap->dbg_detaching = 1;  /* prevent multiple in-progress detaches */
42916 
42917 	if (heap->dbg_write_cb != NULL) {
42918 		duk_hthread *thr;
42919 
42920 		thr = heap->heap_thread;
42921 		DUK_ASSERT(thr != NULL);
42922 
42923 		duk_debug_write_notify(thr, DUK_DBG_CMD_DETACHING);
42924 		duk_debug_write_int(thr, reason);
42925 		duk_debug_write_eom(thr);
42926 	}
42927 
42928 	heap->dbg_read_cb = NULL;
42929 	heap->dbg_write_cb = NULL;
42930 	heap->dbg_peek_cb = NULL;
42931 	heap->dbg_read_flush_cb = NULL;
42932 	heap->dbg_write_flush_cb = NULL;
42933 	heap->dbg_request_cb = NULL;
42934 	/* heap->dbg_detached_cb: keep */
42935 	/* heap->dbg_udata: keep */
42936 	/* heap->dbg_processing: keep on purpose to avoid debugger re-entry in detaching state */
42937 	heap->dbg_state_dirty = 0;
42938 	heap->dbg_force_restart = 0;
42939 	heap->dbg_pause_flags = 0;
42940 	heap->dbg_pause_act = NULL;
42941 	heap->dbg_pause_startline = 0;
42942 	heap->dbg_have_next_byte = 0;
42943 	duk_debug_clear_paused(heap);  /* XXX: some overlap with field inits above */
42944 	heap->dbg_state_dirty = 0;     /* XXX: clear_paused sets dirty; rework? */
42945 
42946 	/* Ensure there are no stale active breakpoint pointers.
42947 	 * Breakpoint list is currently kept - we could empty it
42948 	 * here but we'd need to handle refcounts correctly, and
42949 	 * we'd need a 'thr' reference for that.
42950 	 *
42951 	 * XXX: clear breakpoint on either attach or detach?
42952 	 */
42953 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
42954 }
42955 
42956 DUK_LOCAL void duk__debug_do_detach2(duk_heap *heap) {
42957 	duk_debug_detached_function detached_cb;
42958 	void *detached_udata;
42959 	duk_hthread *thr;
42960 
42961 	thr = heap->heap_thread;
42962 	if (thr == NULL) {
42963 		DUK_ASSERT(heap->dbg_detached_cb == NULL);
42964 		return;
42965 	}
42966 
42967 	/* Safe to call multiple times. */
42968 
42969 	detached_cb = heap->dbg_detached_cb;
42970 	detached_udata = heap->dbg_udata;
42971 	heap->dbg_detached_cb = NULL;
42972 	heap->dbg_udata = NULL;
42973 
42974 	if (detached_cb) {
42975 		/* Careful here: state must be wiped before the call
42976 		 * so that we can cleanly handle a re-attach from
42977 		 * inside the callback.
42978 		 */
42979 		DUK_D(DUK_DPRINT("detached during message loop, delayed call to detached_cb"));
42980 		detached_cb(thr, detached_udata);
42981 	}
42982 
42983 	heap->dbg_detaching = 0;
42984 }
42985 
42986 DUK_INTERNAL void duk_debug_do_detach(duk_heap *heap) {
42987 	duk__debug_do_detach1(heap, 0);
42988 	duk__debug_do_detach2(heap);
42989 }
42990 
42991 /* Called on a read/write error: NULL all callbacks except the detached
42992  * callback so that we never accidentally call them after a read/write
42993  * error has been indicated.  This is especially important for the transport
42994  * I/O callbacks to fulfill guaranteed callback semantics.
42995  */
42996 DUK_LOCAL void duk__debug_null_most_callbacks(duk_hthread *thr) {
42997 	duk_heap *heap;
42998 
42999 	DUK_ASSERT(thr != NULL);
43000 
43001 	heap = thr->heap;
43002 	DUK_D(DUK_DPRINT("transport read/write error, NULL all callbacks expected detached"));
43003 	heap->dbg_read_cb = NULL;
43004 	heap->dbg_write_cb = NULL;  /* this is especially critical to avoid another write call in detach1() */
43005 	heap->dbg_peek_cb = NULL;
43006 	heap->dbg_read_flush_cb = NULL;
43007 	heap->dbg_write_flush_cb = NULL;
43008 	heap->dbg_request_cb = NULL;
43009 	/* keep heap->dbg_detached_cb */
43010 }
43011 
43012 /*
43013  *  Pause handling
43014  */
43015 
43016 DUK_LOCAL void duk__debug_set_pause_state(duk_hthread *thr, duk_heap *heap, duk_small_uint_t pause_flags) {
43017 	duk_uint_fast32_t line;
43018 
43019 	line = duk_debug_curr_line(thr);
43020 	if (line == 0) {
43021 		/* No line info for current function. */
43022 		duk_small_uint_t updated_flags;
43023 
43024 		updated_flags = pause_flags & ~(DUK_PAUSE_FLAG_LINE_CHANGE);
43025 		DUK_D(DUK_DPRINT("no line info for current activation, disable line-based pause flags: 0x%08lx -> 0x%08lx",
43026 		                 (long) pause_flags, (long) updated_flags));
43027 		pause_flags = updated_flags;
43028 	}
43029 
43030 	heap->dbg_pause_flags = pause_flags;
43031 	heap->dbg_pause_act = thr->callstack_curr;
43032 	heap->dbg_pause_startline = (duk_uint32_t) line;
43033 	heap->dbg_state_dirty = 1;
43034 
43035 	DUK_D(DUK_DPRINT("set state for automatic pause triggers, flags=0x%08lx, act=%p, startline=%ld",
43036 	                 (long) heap->dbg_pause_flags, (void *) heap->dbg_pause_act,
43037 	                 (long) heap->dbg_pause_startline));
43038 }
43039 
43040 /*
43041  *  Debug connection peek and flush primitives
43042  */
43043 
43044 DUK_INTERNAL duk_bool_t duk_debug_read_peek(duk_hthread *thr) {
43045 	duk_heap *heap;
43046 	duk_bool_t ret;
43047 
43048 	DUK_ASSERT(thr != NULL);
43049 	heap = thr->heap;
43050 	DUK_ASSERT(heap != NULL);
43051 
43052 	if (heap->dbg_read_cb == NULL) {
43053 		DUK_D(DUK_DPRINT("attempt to peek in detached state, return zero (= no data)"));
43054 		return 0;
43055 	}
43056 	if (heap->dbg_peek_cb == NULL) {
43057 		DUK_DD(DUK_DDPRINT("no peek callback, return zero (= no data)"));
43058 		return 0;
43059 	}
43060 
43061 	DUK__DBG_TPORT_ENTER();
43062 	ret = (duk_bool_t) (heap->dbg_peek_cb(heap->dbg_udata) > 0);
43063 	DUK__DBG_TPORT_EXIT();
43064 	return ret;
43065 }
43066 
43067 DUK_INTERNAL void duk_debug_read_flush(duk_hthread *thr) {
43068 	duk_heap *heap;
43069 
43070 	DUK_ASSERT(thr != NULL);
43071 	heap = thr->heap;
43072 	DUK_ASSERT(heap != NULL);
43073 
43074 	if (heap->dbg_read_cb == NULL) {
43075 		DUK_D(DUK_DPRINT("attempt to read flush in detached state, ignore"));
43076 		return;
43077 	}
43078 	if (heap->dbg_read_flush_cb == NULL) {
43079 		DUK_DD(DUK_DDPRINT("no read flush callback, ignore"));
43080 		return;
43081 	}
43082 
43083 	DUK__DBG_TPORT_ENTER();
43084 	heap->dbg_read_flush_cb(heap->dbg_udata);
43085 	DUK__DBG_TPORT_EXIT();
43086 }
43087 
43088 DUK_INTERNAL void duk_debug_write_flush(duk_hthread *thr) {
43089 	duk_heap *heap;
43090 
43091 	DUK_ASSERT(thr != NULL);
43092 	heap = thr->heap;
43093 	DUK_ASSERT(heap != NULL);
43094 
43095 	if (heap->dbg_read_cb == NULL) {
43096 		DUK_D(DUK_DPRINT("attempt to write flush in detached state, ignore"));
43097 		return;
43098 	}
43099 	if (heap->dbg_write_flush_cb == NULL) {
43100 		DUK_DD(DUK_DDPRINT("no write flush callback, ignore"));
43101 		return;
43102 	}
43103 
43104 	DUK__DBG_TPORT_ENTER();
43105 	heap->dbg_write_flush_cb(heap->dbg_udata);
43106 	DUK__DBG_TPORT_EXIT();
43107 }
43108 
43109 /*
43110  *  Debug connection skip primitives
43111  */
43112 
43113 /* Skip fully. */
43114 DUK_INTERNAL void duk_debug_skip_bytes(duk_hthread *thr, duk_size_t length) {
43115 	duk_uint8_t dummy[64];
43116 	duk_size_t now;
43117 
43118 	DUK_ASSERT(thr != NULL);
43119 
43120 	while (length > 0) {
43121 		now = (length > sizeof(dummy) ? sizeof(dummy) : length);
43122 		duk_debug_read_bytes(thr, dummy, now);
43123 		length -= now;
43124 	}
43125 }
43126 
43127 DUK_INTERNAL void duk_debug_skip_byte(duk_hthread *thr) {
43128 	DUK_ASSERT(thr != NULL);
43129 
43130 	(void) duk_debug_read_byte(thr);
43131 }
43132 
43133 /*
43134  *  Debug connection read primitives
43135  */
43136 
43137 /* Peek ahead in the stream one byte. */
43138 DUK_INTERNAL uint8_t duk_debug_peek_byte(duk_hthread *thr) {
43139 	/* It is important not to call this if the last byte read was an EOM.
43140 	 * Reading ahead in this scenario would cause unnecessary blocking if
43141 	 * another message is not available.
43142 	 */
43143 
43144 	duk_uint8_t x;
43145 
43146 	x = duk_debug_read_byte(thr);
43147 	thr->heap->dbg_have_next_byte = 1;
43148 	thr->heap->dbg_next_byte = x;
43149 	return x;
43150 }
43151 
43152 /* Read fully. */
43153 DUK_INTERNAL void duk_debug_read_bytes(duk_hthread *thr, duk_uint8_t *data, duk_size_t length) {
43154 	duk_heap *heap;
43155 	duk_uint8_t *p;
43156 	duk_size_t left;
43157 	duk_size_t got;
43158 
43159 	DUK_ASSERT(thr != NULL);
43160 	heap = thr->heap;
43161 	DUK_ASSERT(heap != NULL);
43162 	DUK_ASSERT(data != NULL);
43163 
43164 	if (heap->dbg_read_cb == NULL) {
43165 		DUK_D(DUK_DPRINT("attempt to read %ld bytes in detached state, return zero data", (long) length));
43166 		goto fail;
43167 	}
43168 
43169 	/* NOTE: length may be zero */
43170 	p = data;
43171 	if (length >= 1 && heap->dbg_have_next_byte) {
43172 		heap->dbg_have_next_byte = 0;
43173 		*p++ = heap->dbg_next_byte;
43174 	}
43175 	for (;;) {
43176 		left = (duk_size_t) ((data + length) - p);
43177 		if (left == 0) {
43178 			break;
43179 		}
43180 		DUK_ASSERT(heap->dbg_read_cb != NULL);
43181 		DUK_ASSERT(left >= 1);
43182 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43183 		left = 1;
43184 #endif
43185 		DUK__DBG_TPORT_ENTER();
43186 		got = heap->dbg_read_cb(heap->dbg_udata, (char *) p, left);
43187 		DUK__DBG_TPORT_EXIT();
43188 
43189 		if (got == 0 || got > left) {
43190 			DUK_D(DUK_DPRINT("connection error during read, return zero data"));
43191 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43192 			DUK__SET_CONN_BROKEN(thr, 1);
43193 			goto fail;
43194 		}
43195 		p += got;
43196 	}
43197 	return;
43198 
43199  fail:
43200 	duk_memzero((void *) data, (size_t) length);
43201 }
43202 
43203 DUK_INTERNAL duk_uint8_t duk_debug_read_byte(duk_hthread *thr) {
43204 	duk_uint8_t x;
43205 
43206 	x = 0;  /* just in case callback is broken and won't write 'x' */
43207 	duk_debug_read_bytes(thr, &x, 1);
43208 	return x;
43209 }
43210 
43211 DUK_LOCAL duk_uint32_t duk__debug_read_uint32_raw(duk_hthread *thr) {
43212 	duk_uint8_t buf[4];
43213 
43214 	DUK_ASSERT(thr != NULL);
43215 
43216 	duk_debug_read_bytes(thr, buf, 4);
43217 	return ((duk_uint32_t) buf[0] << 24) |
43218 	       ((duk_uint32_t) buf[1] << 16) |
43219 	       ((duk_uint32_t) buf[2] << 8) |
43220 	       (duk_uint32_t) buf[3];
43221 }
43222 
43223 DUK_LOCAL duk_int32_t duk__debug_read_int32_raw(duk_hthread *thr) {
43224 	return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43225 }
43226 
43227 DUK_LOCAL duk_uint16_t duk__debug_read_uint16_raw(duk_hthread *thr) {
43228 	duk_uint8_t buf[2];
43229 
43230 	DUK_ASSERT(thr != NULL);
43231 
43232 	duk_debug_read_bytes(thr, buf, 2);
43233 	return ((duk_uint16_t) buf[0] << 8) |
43234 	       (duk_uint16_t) buf[1];
43235 }
43236 
43237 DUK_INTERNAL duk_int32_t duk_debug_read_int(duk_hthread *thr) {
43238 	duk_small_uint_t x;
43239 	duk_small_uint_t t;
43240 
43241 	DUK_ASSERT(thr != NULL);
43242 
43243 	x = duk_debug_read_byte(thr);
43244 	if (x >= 0xc0) {
43245 		t = duk_debug_read_byte(thr);
43246 		return (duk_int32_t) (((x - 0xc0) << 8) + t);
43247 	} else if (x >= 0x80) {
43248 		return (duk_int32_t) (x - 0x80);
43249 	} else if (x == DUK_DBG_IB_INT4) {
43250 		return (duk_int32_t) duk__debug_read_uint32_raw(thr);
43251 	}
43252 
43253 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43254 	DUK__SET_CONN_BROKEN(thr, 1);
43255 	return 0;
43256 }
43257 
43258 DUK_LOCAL duk_hstring *duk__debug_read_hstring_raw(duk_hthread *thr, duk_uint32_t len) {
43259 	duk_uint8_t buf[31];
43260 	duk_uint8_t *p;
43261 
43262 	if (len <= sizeof(buf)) {
43263 		duk_debug_read_bytes(thr, buf, (duk_size_t) len);
43264 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) len);
43265 	} else {
43266 		p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43267 		DUK_ASSERT(p != NULL);
43268 		duk_debug_read_bytes(thr, p, (duk_size_t) len);
43269 		(void) duk_buffer_to_string(thr, -1);  /* Safety relies on debug client, which is OK. */
43270 	}
43271 
43272 	return duk_require_hstring(thr, -1);
43273 }
43274 
43275 DUK_INTERNAL duk_hstring *duk_debug_read_hstring(duk_hthread *thr) {
43276 	duk_small_uint_t x;
43277 	duk_uint32_t len;
43278 
43279 	DUK_ASSERT(thr != NULL);
43280 
43281 	x = duk_debug_read_byte(thr);
43282 	if (x >= 0x60 && x <= 0x7f) {
43283 		/* For short strings, use a fixed temp buffer. */
43284 		len = (duk_uint32_t) (x - 0x60);
43285 	} else if (x == DUK_DBG_IB_STR2) {
43286 		len = (duk_uint32_t) duk__debug_read_uint16_raw(thr);
43287 	} else if (x == DUK_DBG_IB_STR4) {
43288 		len = (duk_uint32_t) duk__debug_read_uint32_raw(thr);
43289 	} else {
43290 		goto fail;
43291 	}
43292 
43293 	return duk__debug_read_hstring_raw(thr, len);
43294 
43295  fail:
43296 	DUK_D(DUK_DPRINT("debug connection error: failed to decode int"));
43297 	DUK__SET_CONN_BROKEN(thr, 1);
43298 	duk_push_hstring_empty(thr);  /* always push some string */
43299 	return duk_require_hstring(thr, -1);
43300 }
43301 
43302 DUK_LOCAL duk_hbuffer *duk__debug_read_hbuffer_raw(duk_hthread *thr, duk_uint32_t len) {
43303 	duk_uint8_t *p;
43304 
43305 	p = (duk_uint8_t *) duk_push_fixed_buffer(thr, (duk_size_t) len);  /* zero for paranoia */
43306 	DUK_ASSERT(p != NULL);
43307 	duk_debug_read_bytes(thr, p, (duk_size_t) len);
43308 
43309 	return duk_require_hbuffer(thr, -1);
43310 }
43311 
43312 DUK_LOCAL void *duk__debug_read_pointer_raw(duk_hthread *thr) {
43313 	duk_small_uint_t x;
43314 	duk__ptr_union pu;
43315 
43316 	DUK_ASSERT(thr != NULL);
43317 
43318 	x = duk_debug_read_byte(thr);
43319 	if (x != sizeof(pu)) {
43320 		goto fail;
43321 	}
43322 	duk_debug_read_bytes(thr, (duk_uint8_t *) &pu.p, sizeof(pu));
43323 #if defined(DUK_USE_INTEGER_LE)
43324 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43325 #endif
43326 	return (void *) pu.p;
43327 
43328  fail:
43329 	DUK_D(DUK_DPRINT("debug connection error: failed to decode pointer"));
43330 	DUK__SET_CONN_BROKEN(thr, 1);
43331 	return (void *) NULL;
43332 }
43333 
43334 DUK_LOCAL duk_double_t duk__debug_read_double_raw(duk_hthread *thr) {
43335 	duk_double_union du;
43336 
43337 	DUK_ASSERT(sizeof(du.uc) == 8);
43338 	duk_debug_read_bytes(thr, (duk_uint8_t *) du.uc, sizeof(du.uc));
43339 	DUK_DBLUNION_DOUBLE_NTOH(&du);
43340 	return du.d;
43341 }
43342 
43343 #if 0
43344 DUK_INTERNAL duk_heaphdr *duk_debug_read_heapptr(duk_hthread *thr) {
43345 	duk_small_uint_t x;
43346 
43347 	DUK_ASSERT(thr != NULL);
43348 
43349 	x = duk_debug_read_byte(thr);
43350 	if (x != DUK_DBG_IB_HEAPPTR) {
43351 		goto fail;
43352 	}
43353 
43354 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43355 
43356  fail:
43357 	DUK_D(DUK_DPRINT("debug connection error: failed to decode heapptr"));
43358 	DUK__SET_CONN_BROKEN(thr, 1);
43359 	return NULL;
43360 }
43361 #endif
43362 
43363 DUK_INTERNAL duk_heaphdr *duk_debug_read_any_ptr(duk_hthread *thr) {
43364 	duk_small_uint_t x;
43365 
43366 	DUK_ASSERT(thr != NULL);
43367 
43368 	x = duk_debug_read_byte(thr);
43369 	switch (x) {
43370 	case DUK_DBG_IB_OBJECT:
43371 	case DUK_DBG_IB_POINTER:
43372 	case DUK_DBG_IB_HEAPPTR:
43373 		/* Accept any pointer-like value; for 'object' dvalue, read
43374 		 * and ignore the class number.
43375 		 */
43376 		if (x == DUK_DBG_IB_OBJECT) {
43377 			duk_debug_skip_byte(thr);
43378 		}
43379 		break;
43380 	default:
43381 		goto fail;
43382 	}
43383 
43384 	return (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43385 
43386  fail:
43387 	DUK_D(DUK_DPRINT("debug connection error: failed to decode any pointer (object, pointer, heapptr)"));
43388 	DUK__SET_CONN_BROKEN(thr, 1);
43389 	return NULL;
43390 }
43391 
43392 DUK_INTERNAL duk_tval *duk_debug_read_tval(duk_hthread *thr) {
43393 	duk_uint8_t x;
43394 	duk_uint_t t;
43395 	duk_uint32_t len;
43396 
43397 	DUK_ASSERT(thr != NULL);
43398 
43399 	x = duk_debug_read_byte(thr);
43400 
43401 	if (x >= 0xc0) {
43402 		t = (duk_uint_t) (x - 0xc0);
43403 		t = (t << 8) + duk_debug_read_byte(thr);
43404 		duk_push_uint(thr, (duk_uint_t) t);
43405 		goto return_ptr;
43406 	}
43407 	if (x >= 0x80) {
43408 		duk_push_uint(thr, (duk_uint_t) (x - 0x80));
43409 		goto return_ptr;
43410 	}
43411 	if (x >= 0x60) {
43412 		len = (duk_uint32_t) (x - 0x60);
43413 		duk__debug_read_hstring_raw(thr, len);
43414 		goto return_ptr;
43415 	}
43416 
43417 	switch (x) {
43418 	case DUK_DBG_IB_INT4: {
43419 		duk_int32_t i = duk__debug_read_int32_raw(thr);
43420 		duk_push_i32(thr, i);
43421 		break;
43422 	}
43423 	case DUK_DBG_IB_STR4: {
43424 		len = duk__debug_read_uint32_raw(thr);
43425 		duk__debug_read_hstring_raw(thr, len);
43426 		break;
43427 	}
43428 	case DUK_DBG_IB_STR2: {
43429 		len = duk__debug_read_uint16_raw(thr);
43430 		duk__debug_read_hstring_raw(thr, len);
43431 		break;
43432 	}
43433 	case DUK_DBG_IB_BUF4: {
43434 		len = duk__debug_read_uint32_raw(thr);
43435 		duk__debug_read_hbuffer_raw(thr, len);
43436 		break;
43437 	}
43438 	case DUK_DBG_IB_BUF2: {
43439 		len = duk__debug_read_uint16_raw(thr);
43440 		duk__debug_read_hbuffer_raw(thr, len);
43441 		break;
43442 	}
43443 	case DUK_DBG_IB_UNDEFINED: {
43444 		duk_push_undefined(thr);
43445 		break;
43446 	}
43447 	case DUK_DBG_IB_NULL: {
43448 		duk_push_null(thr);
43449 		break;
43450 	}
43451 	case DUK_DBG_IB_TRUE: {
43452 		duk_push_true(thr);
43453 		break;
43454 	}
43455 	case DUK_DBG_IB_FALSE: {
43456 		duk_push_false(thr);
43457 		break;
43458 	}
43459 	case DUK_DBG_IB_NUMBER: {
43460 		duk_double_t d;
43461 		d = duk__debug_read_double_raw(thr);
43462 		duk_push_number(thr, d);
43463 		break;
43464 	}
43465 	case DUK_DBG_IB_OBJECT: {
43466 		duk_heaphdr *h;
43467 		duk_debug_skip_byte(thr);
43468 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43469 		duk_push_heapptr(thr, (void *) h);
43470 		break;
43471 	}
43472 	case DUK_DBG_IB_POINTER: {
43473 		void *ptr;
43474 		ptr = duk__debug_read_pointer_raw(thr);
43475 		duk_push_pointer(thr, ptr);
43476 		break;
43477 	}
43478 	case DUK_DBG_IB_LIGHTFUNC: {
43479 		/* XXX: Not needed for now, so not implemented.  Note that
43480 		 * function pointers may have different size/layout than
43481 		 * a void pointer.
43482 		 */
43483 		DUK_D(DUK_DPRINT("reading lightfunc values unimplemented"));
43484 		goto fail;
43485 	}
43486 	case DUK_DBG_IB_HEAPPTR: {
43487 		duk_heaphdr *h;
43488 		h = (duk_heaphdr *) duk__debug_read_pointer_raw(thr);
43489 		duk_push_heapptr(thr, (void *) h);
43490 		break;
43491 	}
43492 	case DUK_DBG_IB_UNUSED:  /* unused: not accepted in inbound messages */
43493 	default:
43494 		goto fail;
43495 	}
43496 
43497  return_ptr:
43498 	return DUK_GET_TVAL_NEGIDX(thr, -1);
43499 
43500  fail:
43501 	DUK_D(DUK_DPRINT("debug connection error: failed to decode tval"));
43502 	DUK__SET_CONN_BROKEN(thr, 1);
43503 	return NULL;
43504 }
43505 
43506 /*
43507  *  Debug connection write primitives
43508  */
43509 
43510 /* Write fully. */
43511 DUK_INTERNAL void duk_debug_write_bytes(duk_hthread *thr, const duk_uint8_t *data, duk_size_t length) {
43512 	duk_heap *heap;
43513 	const duk_uint8_t *p;
43514 	duk_size_t left;
43515 	duk_size_t got;
43516 
43517 	DUK_ASSERT(thr != NULL);
43518 	DUK_ASSERT(length == 0 || data != NULL);
43519 	heap = thr->heap;
43520 	DUK_ASSERT(heap != NULL);
43521 
43522 	if (heap->dbg_write_cb == NULL) {
43523 		DUK_D(DUK_DPRINT("attempt to write %ld bytes in detached state, ignore", (long) length));
43524 		return;
43525 	}
43526 	if (length == 0) {
43527 		/* Avoid doing an actual write callback with length == 0,
43528 		 * because that's reserved for a write flush.
43529 		 */
43530 		return;
43531 	}
43532 	DUK_ASSERT(data != NULL);
43533 
43534 	p = data;
43535 	for (;;) {
43536 		left = (duk_size_t) ((data + length) - p);
43537 		if (left == 0) {
43538 			break;
43539 		}
43540 		DUK_ASSERT(heap->dbg_write_cb != NULL);
43541 		DUK_ASSERT(left >= 1);
43542 #if defined(DUK_USE_DEBUGGER_TRANSPORT_TORTURE)
43543 		left = 1;
43544 #endif
43545 		DUK__DBG_TPORT_ENTER();
43546 		got = heap->dbg_write_cb(heap->dbg_udata, (const char *) p, left);
43547 		DUK__DBG_TPORT_EXIT();
43548 
43549 		if (got == 0 || got > left) {
43550 			duk__debug_null_most_callbacks(thr);  /* avoid calling write callback in detach1() */
43551 			DUK_D(DUK_DPRINT("connection error during write"));
43552 			DUK__SET_CONN_BROKEN(thr, 1);
43553 			return;
43554 		}
43555 		p += got;
43556 	}
43557 }
43558 
43559 DUK_INTERNAL void duk_debug_write_byte(duk_hthread *thr, duk_uint8_t x) {
43560 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &x, 1);
43561 }
43562 
43563 DUK_INTERNAL void duk_debug_write_unused(duk_hthread *thr) {
43564 	duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43565 }
43566 
43567 DUK_INTERNAL void duk_debug_write_undefined(duk_hthread *thr) {
43568 	duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43569 }
43570 
43571 #if defined(DUK_USE_DEBUGGER_INSPECT)
43572 DUK_INTERNAL void duk_debug_write_null(duk_hthread *thr) {
43573 	duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43574 }
43575 #endif
43576 
43577 DUK_INTERNAL void duk_debug_write_boolean(duk_hthread *thr, duk_uint_t val) {
43578 	duk_debug_write_byte(thr, val ? DUK_DBG_IB_TRUE : DUK_DBG_IB_FALSE);
43579 }
43580 
43581 /* Write signed 32-bit integer. */
43582 DUK_INTERNAL void duk_debug_write_int(duk_hthread *thr, duk_int32_t x) {
43583 	duk_uint8_t buf[5];
43584 	duk_size_t len;
43585 
43586 	DUK_ASSERT(thr != NULL);
43587 
43588 	if (x >= 0 && x <= 0x3fL) {
43589 		buf[0] = (duk_uint8_t) (0x80 + x);
43590 		len = 1;
43591 	} else if (x >= 0 && x <= 0x3fffL) {
43592 		buf[0] = (duk_uint8_t) (0xc0 + (x >> 8));
43593 		buf[1] = (duk_uint8_t) (x & 0xff);
43594 		len = 2;
43595 	} else {
43596 		/* Signed integers always map to 4 bytes now. */
43597 		buf[0] = (duk_uint8_t) DUK_DBG_IB_INT4;
43598 		buf[1] = (duk_uint8_t) ((x >> 24) & 0xff);
43599 		buf[2] = (duk_uint8_t) ((x >> 16) & 0xff);
43600 		buf[3] = (duk_uint8_t) ((x >> 8) & 0xff);
43601 		buf[4] = (duk_uint8_t) (x & 0xff);
43602 		len = 5;
43603 	}
43604 	duk_debug_write_bytes(thr, buf, len);
43605 }
43606 
43607 /* Write unsigned 32-bit integer. */
43608 DUK_INTERNAL void duk_debug_write_uint(duk_hthread *thr, duk_uint32_t x) {
43609 	/* The debugger protocol doesn't support a plain integer encoding for
43610 	 * the full 32-bit unsigned range (only 32-bit signed).  For now,
43611 	 * unsigned 32-bit values simply written as signed ones.  This is not
43612 	 * a concrete issue except for 32-bit heaphdr fields.  Proper solutions
43613 	 * would be to (a) write such integers as IEEE doubles or (b) add an
43614 	 * unsigned 32-bit dvalue.
43615 	 */
43616 	if (x >= 0x80000000UL) {
43617 		DUK_D(DUK_DPRINT("writing unsigned integer 0x%08lx as signed integer",
43618 		                 (long) x));
43619 	}
43620 	duk_debug_write_int(thr, (duk_int32_t) x);
43621 }
43622 
43623 DUK_INTERNAL void duk_debug_write_strbuf(duk_hthread *thr, const char *data, duk_size_t length, duk_uint8_t marker_base) {
43624 	duk_uint8_t buf[5];
43625 	duk_size_t buflen;
43626 
43627 	DUK_ASSERT(thr != NULL);
43628 	DUK_ASSERT(length == 0 || data != NULL);
43629 
43630 	if (length <= 0x1fUL && marker_base == DUK_DBG_IB_STR4) {
43631 		/* For strings, special form for short lengths. */
43632 		buf[0] = (duk_uint8_t) (0x60 + length);
43633 		buflen = 1;
43634 	} else if (length <= 0xffffUL) {
43635 		buf[0] = (duk_uint8_t) (marker_base + 1);
43636 		buf[1] = (duk_uint8_t) (length >> 8);
43637 		buf[2] = (duk_uint8_t) (length & 0xff);
43638 		buflen = 3;
43639 	} else {
43640 		buf[0] = (duk_uint8_t) marker_base;
43641 		buf[1] = (duk_uint8_t) (length >> 24);
43642 		buf[2] = (duk_uint8_t) ((length >> 16) & 0xff);
43643 		buf[3] = (duk_uint8_t) ((length >> 8) & 0xff);
43644 		buf[4] = (duk_uint8_t) (length & 0xff);
43645 		buflen = 5;
43646 	}
43647 
43648 	duk_debug_write_bytes(thr, (const duk_uint8_t *) buf, buflen);
43649 	duk_debug_write_bytes(thr, (const duk_uint8_t *) data, length);
43650 }
43651 
43652 DUK_INTERNAL void duk_debug_write_string(duk_hthread *thr, const char *data, duk_size_t length) {
43653 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_STR4);
43654 }
43655 
43656 DUK_INTERNAL void duk_debug_write_cstring(duk_hthread *thr, const char *data) {
43657 	DUK_ASSERT(thr != NULL);
43658 
43659 	duk_debug_write_string(thr,
43660 	                       data,
43661 	                       data ? DUK_STRLEN(data) : 0);
43662 }
43663 
43664 DUK_INTERNAL void duk_debug_write_hstring(duk_hthread *thr, duk_hstring *h) {
43665 	DUK_ASSERT(thr != NULL);
43666 
43667 	/* XXX: differentiate null pointer from empty string? */
43668 	duk_debug_write_string(thr,
43669 	                       (h != NULL ? (const char *) DUK_HSTRING_GET_DATA(h) : NULL),
43670 	                       (h != NULL ? (duk_size_t) DUK_HSTRING_GET_BYTELEN(h) : 0));
43671 }
43672 
43673 DUK_LOCAL void duk__debug_write_hstring_safe_top(duk_hthread *thr) {
43674 	duk_debug_write_hstring(thr, duk_safe_to_hstring(thr, -1));
43675 }
43676 
43677 DUK_INTERNAL void duk_debug_write_buffer(duk_hthread *thr, const char *data, duk_size_t length) {
43678 	duk_debug_write_strbuf(thr, data, length, DUK_DBG_IB_BUF4);
43679 }
43680 
43681 DUK_INTERNAL void duk_debug_write_hbuffer(duk_hthread *thr, duk_hbuffer *h) {
43682 	DUK_ASSERT(thr != NULL);
43683 
43684 	duk_debug_write_buffer(thr,
43685 	                       (h != NULL ? (const char *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h) : NULL),
43686 	                       (h != NULL ? (duk_size_t) DUK_HBUFFER_GET_SIZE(h) : 0));
43687 }
43688 
43689 DUK_LOCAL void duk__debug_write_pointer_raw(duk_hthread *thr, void *ptr, duk_uint8_t ibyte) {
43690 	duk_uint8_t buf[2];
43691 	duk__ptr_union pu;
43692 
43693 	DUK_ASSERT(thr != NULL);
43694 	DUK_ASSERT(sizeof(ptr) >= 1 && sizeof(ptr) <= 16);
43695 	/* ptr may be NULL */
43696 
43697 	buf[0] = ibyte;
43698 	buf[1] = sizeof(pu);
43699 	duk_debug_write_bytes(thr, buf, 2);
43700 	pu.p = (void *) ptr;
43701 #if defined(DUK_USE_INTEGER_LE)
43702 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43703 #endif
43704 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43705 }
43706 
43707 DUK_INTERNAL void duk_debug_write_pointer(duk_hthread *thr, void *ptr) {
43708 	duk__debug_write_pointer_raw(thr, ptr, DUK_DBG_IB_POINTER);
43709 }
43710 
43711 #if defined(DUK_USE_DEBUGGER_DUMPHEAP) || defined(DUK_USE_DEBUGGER_INSPECT)
43712 DUK_INTERNAL void duk_debug_write_heapptr(duk_hthread *thr, duk_heaphdr *h) {
43713 	duk__debug_write_pointer_raw(thr, (void *) h, DUK_DBG_IB_HEAPPTR);
43714 }
43715 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP || DUK_USE_DEBUGGER_INSPECT */
43716 
43717 DUK_INTERNAL void duk_debug_write_hobject(duk_hthread *thr, duk_hobject *obj) {
43718 	duk_uint8_t buf[3];
43719 	duk__ptr_union pu;
43720 
43721 	DUK_ASSERT(thr != NULL);
43722 	DUK_ASSERT(sizeof(obj) >= 1 && sizeof(obj) <= 16);
43723 	DUK_ASSERT(obj != NULL);
43724 
43725 	buf[0] = DUK_DBG_IB_OBJECT;
43726 	buf[1] = (duk_uint8_t) DUK_HOBJECT_GET_CLASS_NUMBER(obj);
43727 	buf[2] = sizeof(pu);
43728 	duk_debug_write_bytes(thr, buf, 3);
43729 	pu.p = (void *) obj;
43730 #if defined(DUK_USE_INTEGER_LE)
43731 	duk_byteswap_bytes((duk_uint8_t *) pu.b, sizeof(pu));
43732 #endif
43733 	duk_debug_write_bytes(thr, (const duk_uint8_t *) &pu.p, (duk_size_t) sizeof(pu));
43734 }
43735 
43736 DUK_INTERNAL void duk_debug_write_tval(duk_hthread *thr, duk_tval *tv) {
43737 	duk_c_function lf_func;
43738 	duk_small_uint_t lf_flags;
43739 	duk_uint8_t buf[4];
43740 	duk_double_union du1;
43741 	duk_double_union du2;
43742 	duk_int32_t i32;
43743 
43744 	DUK_ASSERT(thr != NULL);
43745 	DUK_ASSERT(tv != NULL);
43746 
43747 	switch (DUK_TVAL_GET_TAG(tv)) {
43748 	case DUK_TAG_UNDEFINED:
43749 		duk_debug_write_byte(thr, DUK_DBG_IB_UNDEFINED);
43750 		break;
43751 	case DUK_TAG_UNUSED:
43752 		duk_debug_write_byte(thr, DUK_DBG_IB_UNUSED);
43753 		break;
43754 	case DUK_TAG_NULL:
43755 		duk_debug_write_byte(thr, DUK_DBG_IB_NULL);
43756 		break;
43757 	case DUK_TAG_BOOLEAN:
43758 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 ||
43759 		           DUK_TVAL_GET_BOOLEAN(tv) == 1);
43760 		duk_debug_write_boolean(thr, DUK_TVAL_GET_BOOLEAN(tv));
43761 		break;
43762 	case DUK_TAG_POINTER:
43763 		duk_debug_write_pointer(thr, (void *) DUK_TVAL_GET_POINTER(tv));
43764 		break;
43765 	case DUK_TAG_LIGHTFUNC:
43766 		DUK_TVAL_GET_LIGHTFUNC(tv, lf_func, lf_flags);
43767 		buf[0] = DUK_DBG_IB_LIGHTFUNC;
43768 		buf[1] = (duk_uint8_t) (lf_flags >> 8);
43769 		buf[2] = (duk_uint8_t) (lf_flags & 0xff);
43770 		buf[3] = sizeof(lf_func);
43771 		duk_debug_write_bytes(thr, buf, 4);
43772 		duk_debug_write_bytes(thr, (const duk_uint8_t *) &lf_func, sizeof(lf_func));
43773 		break;
43774 	case DUK_TAG_STRING:
43775 		duk_debug_write_hstring(thr, DUK_TVAL_GET_STRING(tv));
43776 		break;
43777 	case DUK_TAG_OBJECT:
43778 		duk_debug_write_hobject(thr, DUK_TVAL_GET_OBJECT(tv));
43779 		break;
43780 	case DUK_TAG_BUFFER:
43781 		duk_debug_write_hbuffer(thr, DUK_TVAL_GET_BUFFER(tv));
43782 		break;
43783 #if defined(DUK_USE_FASTINT)
43784 	case DUK_TAG_FASTINT:
43785 #endif
43786 	default:
43787 		/* Numbers are normalized to big (network) endian.  We can
43788 		 * (but are not required) to use integer dvalues when there's
43789 		 * no loss of precision.
43790 		 *
43791 		 * XXX: share check with other code; this check is slow but
43792 		 * reliable and doesn't require careful exponent/mantissa
43793 		 * mask tricks as in the fastint downgrade code.
43794 		 */
43795 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
43796 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
43797 		du1.d = DUK_TVAL_GET_NUMBER(tv);
43798 		i32 = (duk_int32_t) du1.d;
43799 		du2.d = (duk_double_t) i32;
43800 
43801 		DUK_DD(DUK_DDPRINT("i32=%ld du1=%02x%02x%02x%02x%02x%02x%02x%02x "
43802 		                   "du2=%02x%02x%02x%02x%02x%02x%02x%02x",
43803 		                   (long) i32,
43804 		                   (unsigned int) du1.uc[0], (unsigned int) du1.uc[1],
43805 		                   (unsigned int) du1.uc[2], (unsigned int) du1.uc[3],
43806 		                   (unsigned int) du1.uc[4], (unsigned int) du1.uc[5],
43807 		                   (unsigned int) du1.uc[6], (unsigned int) du1.uc[7],
43808 		                   (unsigned int) du2.uc[0], (unsigned int) du2.uc[1],
43809 		                   (unsigned int) du2.uc[2], (unsigned int) du2.uc[3],
43810 		                   (unsigned int) du2.uc[4], (unsigned int) du2.uc[5],
43811 		                   (unsigned int) du2.uc[6], (unsigned int) du2.uc[7]));
43812 
43813 		if (duk_memcmp((const void *) du1.uc, (const void *) du2.uc, sizeof(du1.uc)) == 0) {
43814 			duk_debug_write_int(thr, i32);
43815 		} else {
43816 			DUK_DBLUNION_DOUBLE_HTON(&du1);
43817 			duk_debug_write_byte(thr, DUK_DBG_IB_NUMBER);
43818 			duk_debug_write_bytes(thr, (const duk_uint8_t *) du1.uc, sizeof(du1.uc));
43819 		}
43820 	}
43821 }
43822 
43823 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
43824 /* Variant for writing duk_tvals so that any heap allocated values are
43825  * written out as tagged heap pointers.
43826  */
43827 DUK_LOCAL void duk__debug_write_tval_heapptr(duk_hthread *thr, duk_tval *tv) {
43828 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
43829 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
43830 		duk_debug_write_heapptr(thr, h);
43831 	} else {
43832 		duk_debug_write_tval(thr, tv);
43833 	}
43834 }
43835 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
43836 
43837 /*
43838  *  Debug connection message write helpers
43839  */
43840 
43841 #if 0  /* unused */
43842 DUK_INTERNAL void duk_debug_write_request(duk_hthread *thr, duk_small_uint_t command) {
43843 	duk_debug_write_byte(thr, DUK_DBG_IB_REQUEST);
43844 	duk_debug_write_int(thr, command);
43845 }
43846 #endif
43847 
43848 DUK_INTERNAL void duk_debug_write_reply(duk_hthread *thr) {
43849 	duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
43850 }
43851 
43852 DUK_INTERNAL void duk_debug_write_error_eom(duk_hthread *thr, duk_small_uint_t err_code, const char *msg) {
43853 	/* Allow NULL 'msg' */
43854 	duk_debug_write_byte(thr, DUK_DBG_IB_ERROR);
43855 	duk_debug_write_int(thr, (duk_int32_t) err_code);
43856 	duk_debug_write_cstring(thr, msg);
43857 	duk_debug_write_eom(thr);
43858 }
43859 
43860 DUK_INTERNAL void duk_debug_write_notify(duk_hthread *thr, duk_small_uint_t command) {
43861 	duk_debug_write_byte(thr, DUK_DBG_IB_NOTIFY);
43862 	duk_debug_write_int(thr, (duk_int32_t) command);
43863 }
43864 
43865 DUK_INTERNAL void duk_debug_write_eom(duk_hthread *thr) {
43866 	duk_debug_write_byte(thr, DUK_DBG_IB_EOM);
43867 
43868 	/* As an initial implementation, write flush after every EOM (and the
43869 	 * version identifier).  A better implementation would flush only when
43870 	 * Duktape is finished processing messages so that a flush only happens
43871 	 * after all outbound messages are finished on that occasion.
43872 	 */
43873 	duk_debug_write_flush(thr);
43874 }
43875 
43876 /*
43877  *  Status message and helpers
43878  */
43879 
43880 DUK_INTERNAL duk_uint_fast32_t duk_debug_curr_line(duk_hthread *thr) {
43881 	duk_activation *act;
43882 	duk_uint_fast32_t line;
43883 	duk_uint_fast32_t pc;
43884 
43885 	act = thr->callstack_curr;
43886 	if (act == NULL) {
43887 		return 0;
43888 	}
43889 
43890 	/* We're conceptually between two opcodes; act->pc indicates the next
43891 	 * instruction to be executed.  This is usually the correct pc/line to
43892 	 * indicate in Status.  (For the 'debugger' statement this now reports
43893 	 * the pc/line after the debugger statement because the debugger opcode
43894 	 * has already been executed.)
43895 	 */
43896 
43897 	pc = duk_hthread_get_act_curr_pc(thr, act);
43898 
43899 	/* XXX: this should be optimized to be a raw query and avoid valstack
43900 	 * operations if possible.
43901 	 */
43902 	duk_push_tval(thr, &act->tv_func);
43903 	line = duk_hobject_pc2line_query(thr, -1, pc);
43904 	duk_pop(thr);
43905 	return line;
43906 }
43907 
43908 DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
43909 	duk_activation *act;
43910 
43911 	duk_debug_write_notify(thr, DUK_DBG_CMD_STATUS);
43912 	duk_debug_write_int(thr, (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ? 1 : 0));
43913 
43914 	act = thr->callstack_curr;
43915 	if (act == NULL) {
43916 		duk_debug_write_undefined(thr);
43917 		duk_debug_write_undefined(thr);
43918 		duk_debug_write_int(thr, 0);
43919 		duk_debug_write_int(thr, 0);
43920 	} else {
43921 		duk_push_tval(thr, &act->tv_func);
43922 		duk_get_prop_literal(thr, -1, "fileName");
43923 		duk__debug_write_hstring_safe_top(thr);
43924 		duk_get_prop_literal(thr, -2, "name");
43925 		duk__debug_write_hstring_safe_top(thr);
43926 		duk_pop_3(thr);
43927 		/* Report next pc/line to be executed. */
43928 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
43929 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
43930 	}
43931 
43932 	duk_debug_write_eom(thr);
43933 }
43934 
43935 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
43936 DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
43937 	/*
43938 	 *  NFY <int: 5> <int: fatal> <str: msg> <str: filename> <int: linenumber> EOM
43939 	 */
43940 
43941 	duk_activation *act;
43942 	duk_uint32_t pc;
43943 
43944 	DUK_ASSERT(thr->valstack_top > thr->valstack);  /* At least: ... [err] */
43945 
43946 	duk_debug_write_notify(thr, DUK_DBG_CMD_THROW);
43947 	duk_debug_write_int(thr, (duk_int32_t) fatal);
43948 
43949 	/* Report thrown value to client coerced to string */
43950 	duk_dup_top(thr);
43951 	duk__debug_write_hstring_safe_top(thr);
43952 	duk_pop(thr);
43953 
43954 	if (duk_is_error(thr, -1)) {
43955 		/* Error instance, use augmented error data directly */
43956 		duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
43957 		duk__debug_write_hstring_safe_top(thr);
43958 		duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER);
43959 		duk_debug_write_uint(thr, duk_get_uint(thr, -1));
43960 		duk_pop_2(thr);
43961 	} else {
43962 		/* For anything other than an Error instance, we calculate the
43963 		 * error location directly from the current activation if one
43964 		 * exists.
43965 		 */
43966 		act = thr->callstack_curr;
43967 		if (act != NULL) {
43968 			duk_push_tval(thr, &act->tv_func);
43969 			duk_get_prop_literal(thr, -1, "fileName");
43970 			duk__debug_write_hstring_safe_top(thr);
43971 			pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr, act);
43972 			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(thr, -2, pc));
43973 			duk_pop_2(thr);
43974 		} else {
43975 			/* Can happen if duk_throw() is called on an empty
43976 			 * callstack.
43977 			 */
43978 			duk_debug_write_cstring(thr, "");
43979 			duk_debug_write_uint(thr, 0);
43980 		}
43981 	}
43982 
43983 	duk_debug_write_eom(thr);
43984 }
43985 #endif  /* DUK_USE_DEBUGGER_THROW_NOTIFY */
43986 
43987 /*
43988  *  Debug message processing
43989  */
43990 
43991 /* Skip dvalue. */
43992 DUK_LOCAL duk_bool_t duk__debug_skip_dvalue(duk_hthread *thr) {
43993 	duk_uint8_t x;
43994 	duk_uint32_t len;
43995 
43996 	x = duk_debug_read_byte(thr);
43997 
43998 	if (x >= 0xc0) {
43999 		duk_debug_skip_byte(thr);
44000 		return 0;
44001 	}
44002 	if (x >= 0x80) {
44003 		return 0;
44004 	}
44005 	if (x >= 0x60) {
44006 		duk_debug_skip_bytes(thr, (duk_size_t) (x - 0x60));
44007 		return 0;
44008 	}
44009 	switch(x) {
44010 	case DUK_DBG_IB_EOM:
44011 		return 1;  /* Return 1: got EOM */
44012 	case DUK_DBG_IB_REQUEST:
44013 	case DUK_DBG_IB_REPLY:
44014 	case DUK_DBG_IB_ERROR:
44015 	case DUK_DBG_IB_NOTIFY:
44016 		break;
44017 	case DUK_DBG_IB_INT4:
44018 		(void) duk__debug_read_uint32_raw(thr);
44019 		break;
44020 	case DUK_DBG_IB_STR4:
44021 	case DUK_DBG_IB_BUF4:
44022 		len = duk__debug_read_uint32_raw(thr);
44023 		duk_debug_skip_bytes(thr, len);
44024 		break;
44025 	case DUK_DBG_IB_STR2:
44026 	case DUK_DBG_IB_BUF2:
44027 		len = duk__debug_read_uint16_raw(thr);
44028 		duk_debug_skip_bytes(thr, len);
44029 		break;
44030 	case DUK_DBG_IB_UNUSED:
44031 	case DUK_DBG_IB_UNDEFINED:
44032 	case DUK_DBG_IB_NULL:
44033 	case DUK_DBG_IB_TRUE:
44034 	case DUK_DBG_IB_FALSE:
44035 		break;
44036 	case DUK_DBG_IB_NUMBER:
44037 		duk_debug_skip_bytes(thr, 8);
44038 		break;
44039 	case DUK_DBG_IB_OBJECT:
44040 		duk_debug_skip_byte(thr);
44041 		len = duk_debug_read_byte(thr);
44042 		duk_debug_skip_bytes(thr, len);
44043 		break;
44044 	case DUK_DBG_IB_POINTER:
44045 	case DUK_DBG_IB_HEAPPTR:
44046 		len = duk_debug_read_byte(thr);
44047 		duk_debug_skip_bytes(thr, len);
44048 		break;
44049 	case DUK_DBG_IB_LIGHTFUNC:
44050 		duk_debug_skip_bytes(thr, 2);
44051 		len = duk_debug_read_byte(thr);
44052 		duk_debug_skip_bytes(thr, len);
44053 		break;
44054 	default:
44055 		goto fail;
44056 	}
44057 
44058 	return 0;
44059 
44060  fail:
44061 	DUK__SET_CONN_BROKEN(thr, 1);
44062 	return 1;  /* Pretend like we got EOM */
44063 }
44064 
44065 /* Skip dvalues to EOM. */
44066 DUK_LOCAL void duk__debug_skip_to_eom(duk_hthread *thr) {
44067 	for (;;) {
44068 		if (duk__debug_skip_dvalue(thr)) {
44069 			break;
44070 		}
44071 	}
44072 }
44073 
44074 /* Read and validate a call stack index.  If index is invalid, write out an
44075  * error message and return zero.
44076  */
44077 DUK_LOCAL duk_int32_t duk__debug_read_validate_csindex(duk_hthread *thr) {
44078 	duk_int32_t level;
44079 	level = duk_debug_read_int(thr);
44080 	if (level >= 0 || -level > (duk_int32_t) thr->callstack_top) {
44081 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44082 		return 0;  /* zero indicates failure */
44083 	}
44084 	return level;
44085 }
44086 
44087 /* Read a call stack index and lookup the corresponding duk_activation.
44088  * If index is invalid, write out an error message and return NULL.
44089  */
44090 DUK_LOCAL duk_activation *duk__debug_read_level_get_activation(duk_hthread *thr) {
44091 	duk_activation *act;
44092 	duk_int32_t level;
44093 
44094 	level = duk_debug_read_int(thr);
44095 	act = duk_hthread_get_activation_for_level(thr, level);
44096 	if (act == NULL) {
44097 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44098 	}
44099 	return act;
44100 }
44101 
44102 /*
44103  *  Simple commands
44104  */
44105 
44106 DUK_LOCAL void duk__debug_handle_basic_info(duk_hthread *thr, duk_heap *heap) {
44107 	DUK_UNREF(heap);
44108 	DUK_D(DUK_DPRINT("debug command Version"));
44109 
44110 	duk_debug_write_reply(thr);
44111 	duk_debug_write_int(thr, DUK_VERSION);
44112 	duk_debug_write_cstring(thr, DUK_GIT_DESCRIBE);
44113 	duk_debug_write_cstring(thr, DUK_USE_TARGET_INFO);
44114 #if defined(DUK_USE_DOUBLE_LE)
44115 	duk_debug_write_int(thr, 1);
44116 #elif defined(DUK_USE_DOUBLE_ME)
44117 	duk_debug_write_int(thr, 2);
44118 #elif defined(DUK_USE_DOUBLE_BE)
44119 	duk_debug_write_int(thr, 3);
44120 #else
44121 	duk_debug_write_int(thr, 0);
44122 #endif
44123 	duk_debug_write_int(thr, (duk_int_t) sizeof(void *));
44124 	duk_debug_write_eom(thr);
44125 }
44126 
44127 DUK_LOCAL void duk__debug_handle_trigger_status(duk_hthread *thr, duk_heap *heap) {
44128 	DUK_UNREF(heap);
44129 	DUK_D(DUK_DPRINT("debug command TriggerStatus"));
44130 
44131 	duk_debug_write_reply(thr);
44132 	duk_debug_write_eom(thr);
44133 	heap->dbg_state_dirty = 1;
44134 }
44135 
44136 DUK_LOCAL void duk__debug_handle_pause(duk_hthread *thr, duk_heap *heap) {
44137 	DUK_D(DUK_DPRINT("debug command Pause"));
44138 	duk_debug_set_paused(heap);
44139 	duk_debug_write_reply(thr);
44140 	duk_debug_write_eom(thr);
44141 }
44142 
44143 DUK_LOCAL void duk__debug_handle_resume(duk_hthread *thr, duk_heap *heap) {
44144 	duk_small_uint_t pause_flags;
44145 
44146 	DUK_D(DUK_DPRINT("debug command Resume"));
44147 
44148 	duk_debug_clear_paused(heap);
44149 
44150 	pause_flags = 0;
44151 #if 0  /* manual testing */
44152 	pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE;
44153 	pause_flags |= DUK_PAUSE_FLAG_CAUGHT_ERROR;
44154 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44155 #endif
44156 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44157 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44158 #endif
44159 
44160 	duk__debug_set_pause_state(thr, heap, pause_flags);
44161 
44162 	duk_debug_write_reply(thr);
44163 	duk_debug_write_eom(thr);
44164 }
44165 
44166 DUK_LOCAL void duk__debug_handle_step(duk_hthread *thr, duk_heap *heap, duk_int32_t cmd) {
44167 	duk_small_uint_t pause_flags;
44168 
44169 	DUK_D(DUK_DPRINT("debug command StepInto/StepOver/StepOut: %d", (int) cmd));
44170 
44171 	if (cmd == DUK_DBG_CMD_STEPINTO) {
44172 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44173 		              DUK_PAUSE_FLAG_FUNC_ENTRY |
44174 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44175 	} else if (cmd == DUK_DBG_CMD_STEPOVER) {
44176 		pause_flags = DUK_PAUSE_FLAG_LINE_CHANGE |
44177 		              DUK_PAUSE_FLAG_FUNC_EXIT;
44178 	} else {
44179 		DUK_ASSERT(cmd == DUK_DBG_CMD_STEPOUT);
44180 		pause_flags = DUK_PAUSE_FLAG_FUNC_EXIT;
44181 	}
44182 #if defined(DUK_USE_DEBUGGER_PAUSE_UNCAUGHT)
44183 	pause_flags |= DUK_PAUSE_FLAG_UNCAUGHT_ERROR;
44184 #endif
44185 
44186 	/* If current activation doesn't have line information, line-based
44187 	 * pause flags are automatically disabled.  As a result, e.g.
44188 	 * StepInto will then pause on (native) function entry or exit.
44189 	 */
44190 	duk_debug_clear_paused(heap);
44191 	duk__debug_set_pause_state(thr, heap, pause_flags);
44192 
44193 	duk_debug_write_reply(thr);
44194 	duk_debug_write_eom(thr);
44195 }
44196 
44197 DUK_LOCAL void duk__debug_handle_list_break(duk_hthread *thr, duk_heap *heap) {
44198 	duk_small_int_t i;
44199 
44200 	DUK_D(DUK_DPRINT("debug command ListBreak"));
44201 	duk_debug_write_reply(thr);
44202 	for (i = 0; i < (duk_small_int_t) heap->dbg_breakpoint_count; i++) {
44203 		duk_debug_write_hstring(thr, heap->dbg_breakpoints[i].filename);
44204 		duk_debug_write_uint(thr, (duk_uint32_t) heap->dbg_breakpoints[i].line);
44205 	}
44206 	duk_debug_write_eom(thr);
44207 }
44208 
44209 DUK_LOCAL void duk__debug_handle_add_break(duk_hthread *thr, duk_heap *heap) {
44210 	duk_hstring *filename;
44211 	duk_uint32_t linenumber;
44212 	duk_small_int_t idx;
44213 
44214 	DUK_UNREF(heap);
44215 
44216 	filename = duk_debug_read_hstring(thr);
44217 	linenumber = (duk_uint32_t) duk_debug_read_int(thr);
44218 	DUK_D(DUK_DPRINT("debug command AddBreak: %!O:%ld", (duk_hobject *) filename, (long) linenumber));
44219 	idx = duk_debug_add_breakpoint(thr, filename, linenumber);
44220 	if (idx >= 0) {
44221 		duk_debug_write_reply(thr);
44222 		duk_debug_write_int(thr, (duk_int32_t) idx);
44223 		duk_debug_write_eom(thr);
44224 	} else {
44225 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_TOOMANY, "no space for breakpoint");
44226 	}
44227 }
44228 
44229 DUK_LOCAL void duk__debug_handle_del_break(duk_hthread *thr, duk_heap *heap) {
44230 	duk_small_uint_t idx;
44231 
44232 	DUK_UNREF(heap);
44233 
44234 	DUK_D(DUK_DPRINT("debug command DelBreak"));
44235 	idx = (duk_small_uint_t) duk_debug_read_int(thr);
44236 	if (duk_debug_remove_breakpoint(thr, idx)) {
44237 		duk_debug_write_reply(thr);
44238 		duk_debug_write_eom(thr);
44239 	} else {
44240 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid breakpoint index");
44241 	}
44242 }
44243 
44244 DUK_LOCAL void duk__debug_handle_get_var(duk_hthread *thr, duk_heap *heap) {
44245 	duk_activation *act;
44246 	duk_hstring *str;
44247 	duk_bool_t rc;
44248 
44249 	DUK_UNREF(heap);
44250 	DUK_D(DUK_DPRINT("debug command GetVar"));
44251 
44252 	act = duk__debug_read_level_get_activation(thr);
44253 	if (act == NULL) {
44254 		return;
44255 	}
44256 	str = duk_debug_read_hstring(thr);  /* push to stack */
44257 	DUK_ASSERT(str != NULL);
44258 
44259 	rc = duk_js_getvar_activation(thr, act, str, 0);
44260 
44261 	duk_debug_write_reply(thr);
44262 	if (rc) {
44263 		duk_debug_write_int(thr, 1);
44264 		DUK_ASSERT(duk_get_tval(thr, -2) != NULL);
44265 		duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44266 	} else {
44267 		duk_debug_write_int(thr, 0);
44268 		duk_debug_write_unused(thr);
44269 	}
44270 	duk_debug_write_eom(thr);
44271 }
44272 
44273 DUK_LOCAL void duk__debug_handle_put_var(duk_hthread *thr, duk_heap *heap) {
44274 	duk_activation *act;
44275 	duk_hstring *str;
44276 	duk_tval *tv;
44277 
44278 	DUK_UNREF(heap);
44279 	DUK_D(DUK_DPRINT("debug command PutVar"));
44280 
44281 	act = duk__debug_read_level_get_activation(thr);
44282 	if (act == NULL) {
44283 		return;
44284 	}
44285 	str = duk_debug_read_hstring(thr);  /* push to stack */
44286 	DUK_ASSERT(str != NULL);
44287 	tv = duk_debug_read_tval(thr);
44288 	if (tv == NULL) {
44289 		/* detached */
44290 		return;
44291 	}
44292 
44293 	duk_js_putvar_activation(thr, act, str, tv, 0);
44294 
44295 	/* XXX: Current putvar implementation doesn't have a success flag,
44296 	 * add one and send to debug client?
44297 	 */
44298 	duk_debug_write_reply(thr);
44299 	duk_debug_write_eom(thr);
44300 }
44301 
44302 DUK_LOCAL void duk__debug_handle_get_call_stack(duk_hthread *thr, duk_heap *heap) {
44303 	duk_hthread *curr_thr = thr;
44304 	duk_activation *curr_act;
44305 	duk_uint_fast32_t pc;
44306 	duk_uint_fast32_t line;
44307 
44308 	DUK_ASSERT(thr != NULL);
44309 	DUK_UNREF(heap);
44310 
44311 	duk_debug_write_reply(thr);
44312 	while (curr_thr != NULL) {
44313 		for (curr_act = curr_thr->callstack_curr; curr_act != NULL; curr_act = curr_act->parent) {
44314 			/* PC/line semantics here are:
44315 			 *   - For callstack top we're conceptually between two
44316 			 *     opcodes and current PC indicates next line to
44317 			 *     execute, so report that (matches Status).
44318 			 *   - For other activations we're conceptually still
44319 			 *     executing the instruction at PC-1, so report that
44320 			 *     (matches error stacktrace behavior).
44321 			 *   - See: https://github.com/svaarala/duktape/issues/281
44322 			 */
44323 
44324 			/* XXX: optimize to use direct reads, i.e. avoid
44325 			 * value stack operations.
44326 			 */
44327 			duk_push_tval(thr, &curr_act->tv_func);
44328 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
44329 			duk__debug_write_hstring_safe_top(thr);
44330 			duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
44331 			duk__debug_write_hstring_safe_top(thr);
44332 			pc = duk_hthread_get_act_curr_pc(thr, curr_act);
44333 			if (curr_act != curr_thr->callstack_curr && pc > 0) {
44334 				pc--;
44335 			}
44336 			line = duk_hobject_pc2line_query(thr, -3, pc);
44337 			duk_debug_write_uint(thr, (duk_uint32_t) line);
44338 			duk_debug_write_uint(thr, (duk_uint32_t) pc);
44339 			duk_pop_3(thr);
44340 		}
44341 		curr_thr = curr_thr->resumer;
44342 	}
44343 	/* SCANBUILD: warning about 'thr' potentially being NULL here,
44344 	 * warning is incorrect because thr != NULL always here.
44345 	 */
44346 	duk_debug_write_eom(thr);
44347 }
44348 
44349 DUK_LOCAL void duk__debug_handle_get_locals(duk_hthread *thr, duk_heap *heap) {
44350 	duk_activation *act;
44351 	duk_hstring *varname;
44352 
44353 	DUK_UNREF(heap);
44354 
44355 	act = duk__debug_read_level_get_activation(thr);
44356 	if (act == NULL) {
44357 		return;
44358 	}
44359 
44360 	duk_debug_write_reply(thr);
44361 
44362 	/* XXX: several nice-to-have improvements here:
44363 	 *   - Use direct reads avoiding value stack operations
44364 	 *   - Avoid triggering getters, indicate getter values to debug client
44365 	 *   - If side effects are possible, add error catching
44366 	 */
44367 
44368 	duk_push_tval(thr, &act->tv_func);
44369 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_VARMAP);
44370 	if (duk_is_object(thr, -1)) {
44371 		duk_enum(thr, -1, 0 /*enum_flags*/);
44372 		while (duk_next(thr, -1 /*enum_index*/, 0 /*get_value*/)) {
44373 			varname = duk_known_hstring(thr, -1);
44374 
44375 			duk_js_getvar_activation(thr, act, varname, 0 /*throw_flag*/);
44376 			/* [ ... func varmap enum key value this ] */
44377 			duk_debug_write_hstring(thr, duk_get_hstring(thr, -3));
44378 			duk_debug_write_tval(thr, duk_get_tval(thr, -2));
44379 			duk_pop_3(thr);  /* -> [ ... func varmap enum ] */
44380 		}
44381 	} else {
44382 		DUK_D(DUK_DPRINT("varmap is not an object in GetLocals, ignore"));
44383 	}
44384 
44385 	duk_debug_write_eom(thr);
44386 }
44387 
44388 DUK_LOCAL void duk__debug_handle_eval(duk_hthread *thr, duk_heap *heap) {
44389 	duk_small_uint_t call_flags;
44390 	duk_int_t call_ret;
44391 	duk_small_int_t eval_err;
44392 	duk_bool_t direct_eval;
44393 	duk_int32_t level;
44394 	duk_idx_t idx_func;
44395 
44396 	DUK_UNREF(heap);
44397 
44398 	DUK_D(DUK_DPRINT("debug command Eval"));
44399 
44400 	/* The eval code is executed within the lexical environment of a specified
44401 	 * activation.  For now, use global object eval() function, with the eval
44402 	 * considered a 'direct call to eval'.
44403 	 *
44404 	 * Callstack index for debug commands only affects scope -- the callstack
44405 	 * as seen by, e.g. Duktape.act() will be the same regardless.
44406 	 */
44407 
44408 	/* nargs == 2 so we can pass a callstack index to eval(). */
44409 	idx_func = duk_get_top(thr);
44410 	duk_push_c_function(thr, duk_bi_global_object_eval, 2 /*nargs*/);
44411 	duk_push_undefined(thr);  /* 'this' binding shouldn't matter here */
44412 
44413 	/* Read callstack index, if non-null. */
44414 	if (duk_debug_peek_byte(thr) == DUK_DBG_IB_NULL) {
44415 		direct_eval = 0;
44416 		level = -1;  /* Not needed, but silences warning. */
44417 		(void) duk_debug_read_byte(thr);
44418 	} else {
44419 		direct_eval = 1;
44420 		level = duk__debug_read_validate_csindex(thr);
44421 		if (level == 0) {
44422 			return;
44423 		}
44424 	}
44425 
44426 	DUK_ASSERT(!direct_eval ||
44427 	           (level < 0 && -level <= (duk_int32_t) thr->callstack_top));
44428 
44429 	(void) duk_debug_read_hstring(thr);
44430 	if (direct_eval) {
44431 		duk_push_int(thr, level - 1);  /* compensate for eval() call */
44432 	}
44433 
44434 	/* [ ... eval "eval" eval_input level? ] */
44435 
44436 	call_flags = 0;
44437 	if (direct_eval) {
44438 		duk_activation *act;
44439 		duk_hobject *fun;
44440 
44441 		act = duk_hthread_get_activation_for_level(thr, level);
44442 		if (act != NULL) {
44443 			fun = DUK_ACT_GET_FUNC(act);
44444 			if (fun != NULL && DUK_HOBJECT_IS_COMPFUNC(fun)) {
44445 				/* Direct eval requires that there's a current
44446 				 * activation and it is an ECMAScript function.
44447 				 * When Eval is executed from e.g. cooperate API
44448 				 * call we'll need to do an indirect eval instead.
44449 				 */
44450 				call_flags |= DUK_CALL_FLAG_DIRECT_EVAL;
44451 			}
44452 		}
44453 	}
44454 
44455 	call_ret = duk_pcall_method_flags(thr, duk_get_top(thr) - (idx_func + 2), call_flags);
44456 
44457 	if (call_ret == DUK_EXEC_SUCCESS) {
44458 		eval_err = 0;
44459 		/* Use result value as is. */
44460 	} else {
44461 		/* For errors a string coerced result is most informative
44462 		 * right now, as the debug client doesn't have the capability
44463 		 * to traverse the error object.
44464 		 */
44465 		eval_err = 1;
44466 		duk_safe_to_string(thr, -1);
44467 	}
44468 
44469 	/* [ ... result ] */
44470 
44471 	duk_debug_write_reply(thr);
44472 	duk_debug_write_int(thr, (duk_int32_t) eval_err);
44473 	DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
44474 	duk_debug_write_tval(thr, duk_get_tval(thr, -1));
44475 	duk_debug_write_eom(thr);
44476 }
44477 
44478 DUK_LOCAL void duk__debug_handle_detach(duk_hthread *thr, duk_heap *heap) {
44479 	DUK_UNREF(heap);
44480 	DUK_D(DUK_DPRINT("debug command Detach"));
44481 
44482 	duk_debug_write_reply(thr);
44483 	duk_debug_write_eom(thr);
44484 
44485 	DUK_D(DUK_DPRINT("debug connection detached, mark broken"));
44486 	DUK__SET_CONN_BROKEN(thr, 0);  /* not an error */
44487 }
44488 
44489 DUK_LOCAL void duk__debug_handle_apprequest(duk_hthread *thr, duk_heap *heap) {
44490 	duk_idx_t old_top;
44491 
44492 	DUK_D(DUK_DPRINT("debug command AppRequest"));
44493 
44494 	old_top = duk_get_top(thr);  /* save stack top */
44495 
44496 	if (heap->dbg_request_cb != NULL) {
44497 		duk_idx_t nrets;
44498 		duk_idx_t nvalues = 0;
44499 		duk_idx_t top, idx;
44500 
44501 		/* Read tvals from the message and push them onto the valstack,
44502 		 * then call the request callback to process the request.
44503 		 */
44504 		while (duk_debug_peek_byte(thr) != DUK_DBG_IB_EOM) {
44505 			duk_tval *tv;
44506 			if (!duk_check_stack(thr, 1)) {
44507 				DUK_D(DUK_DPRINT("failed to allocate space for request dvalue(s)"));
44508 				goto fail;
44509 			}
44510 			tv = duk_debug_read_tval(thr);  /* push to stack */
44511 			if (tv == NULL) {
44512 				/* detached */
44513 				return;
44514 			}
44515 			nvalues++;
44516 		}
44517 		DUK_ASSERT(duk_get_top(thr) == old_top + nvalues);
44518 
44519 		/* Request callback should push values for reply to client onto valstack */
44520 		DUK_D(DUK_DPRINT("calling into AppRequest request_cb with nvalues=%ld, old_top=%ld, top=%ld",
44521 		                 (long) nvalues, (long) old_top, (long) duk_get_top(thr)));
44522 		nrets = heap->dbg_request_cb(thr, heap->dbg_udata, nvalues);
44523 		DUK_D(DUK_DPRINT("returned from AppRequest request_cb; nvalues=%ld -> nrets=%ld, old_top=%ld, top=%ld",
44524 		                 (long) nvalues, (long) nrets, (long) old_top, (long) duk_get_top(thr)));
44525 		if (nrets >= 0) {
44526 			DUK_ASSERT(duk_get_top(thr) >= old_top + nrets);
44527 			if (duk_get_top(thr) < old_top + nrets) {
44528 				DUK_D(DUK_DPRINT("AppRequest callback doesn't match value stack configuration, "
44529 				                 "top=%ld < old_top=%ld + nrets=%ld; "
44530 				                 "this might mean it's unsafe to continue!",
44531 				                 (long) duk_get_top(thr), (long) old_top, (long) nrets));
44532 				goto fail;
44533 			}
44534 
44535 			/* Reply with tvals pushed by request callback */
44536 			duk_debug_write_byte(thr, DUK_DBG_IB_REPLY);
44537 			top = duk_get_top(thr);
44538 			for (idx = top - nrets; idx < top; idx++) {
44539 				duk_debug_write_tval(thr, DUK_GET_TVAL_POSIDX(thr, idx));
44540 			}
44541 			duk_debug_write_eom(thr);
44542 		} else {
44543 			DUK_ASSERT(duk_get_top(thr) >= old_top + 1);
44544 			if (duk_get_top(thr) < old_top + 1) {
44545 				DUK_D(DUK_DPRINT("request callback return value doesn't match value stack configuration"));
44546 				goto fail;
44547 			}
44548 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_APPLICATION, duk_get_string(thr, -1));
44549 		}
44550 
44551 		duk_set_top(thr, old_top);  /* restore stack top */
44552 	} else {
44553 		DUK_D(DUK_DPRINT("no request callback, treat AppRequest as unsupported"));
44554 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "AppRequest unsupported by target");
44555 	}
44556 
44557 	return;
44558 
44559  fail:
44560 	duk_set_top(thr, old_top);  /* restore stack top */
44561 	DUK__SET_CONN_BROKEN(thr, 1);
44562 }
44563 
44564 /*
44565  *  DumpHeap command
44566  */
44567 
44568 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
44569 /* XXX: this has some overlap with object inspection; remove this and make
44570  * DumpHeap return lists of heapptrs instead?
44571  */
44572 DUK_LOCAL void duk__debug_dump_heaphdr(duk_hthread *thr, duk_heap *heap, duk_heaphdr *hdr) {
44573 	DUK_UNREF(heap);
44574 
44575 	duk_debug_write_heapptr(thr, hdr);
44576 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_TYPE(hdr));
44577 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_FLAGS_RAW(hdr));
44578 #if defined(DUK_USE_REFERENCE_COUNTING)
44579 	duk_debug_write_uint(thr, (duk_uint32_t) DUK_HEAPHDR_GET_REFCOUNT(hdr));
44580 #else
44581 	duk_debug_write_int(thr, (duk_int32_t) -1);
44582 #endif
44583 
44584 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
44585 	case DUK_HTYPE_STRING: {
44586 		duk_hstring *h = (duk_hstring *) hdr;
44587 
44588 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_BYTELEN(h));
44589 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_CHARLEN(h));
44590 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
44591 		duk_debug_write_hstring(thr, h);
44592 		break;
44593 	}
44594 	case DUK_HTYPE_OBJECT: {
44595 		duk_hobject *h = (duk_hobject *) hdr;
44596 		duk_hstring *k;
44597 		duk_uint_fast32_t i;
44598 
44599 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_CLASS_NUMBER(h));
44600 		duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
44601 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ESIZE(h));
44602 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ENEXT(h));
44603 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_ASIZE(h));
44604 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_GET_HSIZE(h));
44605 
44606 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
44607 			duk_debug_write_uint(thr, (duk_uint32_t) DUK_HOBJECT_E_GET_FLAGS(heap, h, i));
44608 			k = DUK_HOBJECT_E_GET_KEY(heap, h, i);
44609 			duk_debug_write_heapptr(thr, (duk_heaphdr *) k);
44610 			if (k == NULL) {
44611 				duk_debug_write_int(thr, 0);  /* isAccessor */
44612 				duk_debug_write_unused(thr);
44613 				continue;
44614 			}
44615 			if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
44616 				duk_debug_write_int(thr, 1);  /* isAccessor */
44617 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
44618 				duk_debug_write_heapptr(thr, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
44619 			} else {
44620 				duk_debug_write_int(thr, 0);  /* isAccessor */
44621 
44622 				duk__debug_write_tval_heapptr(thr, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
44623 			}
44624 		}
44625 
44626 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
44627 			/* Note: array dump will include elements beyond
44628 			 * 'length'.
44629 			 */
44630 			duk__debug_write_tval_heapptr(thr, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
44631 		}
44632 		break;
44633 	}
44634 	case DUK_HTYPE_BUFFER: {
44635 		duk_hbuffer *h = (duk_hbuffer *) hdr;
44636 
44637 		duk_debug_write_uint(thr, (duk_uint32_t) DUK_HBUFFER_GET_SIZE(h));
44638 		duk_debug_write_buffer(thr, (const char *) DUK_HBUFFER_GET_DATA_PTR(heap, h), (duk_size_t) DUK_HBUFFER_GET_SIZE(h));
44639 		break;
44640 	}
44641 	default: {
44642 		DUK_D(DUK_DPRINT("invalid htype: %d", (int) DUK_HEAPHDR_GET_TYPE(hdr)));
44643 	}
44644 	}
44645 }
44646 
44647 DUK_LOCAL void duk__debug_dump_heap_allocated(duk_hthread *thr, duk_heap *heap) {
44648 	duk_heaphdr *hdr;
44649 
44650 	hdr = heap->heap_allocated;
44651 	while (hdr != NULL) {
44652 		duk__debug_dump_heaphdr(thr, heap, hdr);
44653 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
44654 	}
44655 }
44656 
44657 DUK_LOCAL void duk__debug_dump_strtab(duk_hthread *thr, duk_heap *heap) {
44658 	duk_uint32_t i;
44659 	duk_hstring *h;
44660 
44661 	for (i = 0; i < heap->st_size; i++) {
44662 #if defined(DUK_USE_STRTAB_PTRCOMP)
44663 		h = DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, heap->strtable16[i]);
44664 #else
44665 		h = heap->strtable[i];
44666 #endif
44667 		while (h != NULL) {
44668 			duk__debug_dump_heaphdr(thr, heap, (duk_heaphdr *) h);
44669 			h = h->hdr.h_next;
44670 		}
44671 	}
44672 }
44673 
44674 DUK_LOCAL void duk__debug_handle_dump_heap(duk_hthread *thr, duk_heap *heap) {
44675 	DUK_D(DUK_DPRINT("debug command DumpHeap"));
44676 
44677 	duk_debug_write_reply(thr);
44678 	duk__debug_dump_heap_allocated(thr, heap);
44679 	duk__debug_dump_strtab(thr, heap);
44680 	duk_debug_write_eom(thr);
44681 }
44682 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
44683 
44684 DUK_LOCAL void duk__debug_handle_get_bytecode(duk_hthread *thr, duk_heap *heap) {
44685 	duk_activation *act;
44686 	duk_hcompfunc *fun = NULL;
44687 	duk_size_t i, n;
44688 	duk_tval *tv;
44689 	duk_hobject **fn;
44690 	duk_int32_t level = -1;
44691 	duk_uint8_t ibyte;
44692 
44693 	DUK_UNREF(heap);
44694 
44695 	DUK_D(DUK_DPRINT("debug command GetBytecode"));
44696 
44697 	ibyte = duk_debug_peek_byte(thr);
44698 	if (ibyte != DUK_DBG_IB_EOM) {
44699 		tv = duk_debug_read_tval(thr);
44700 		if (tv == NULL) {
44701 			/* detached */
44702 			return;
44703 		}
44704 		if (DUK_TVAL_IS_OBJECT(tv)) {
44705 			/* tentative, checked later */
44706 			fun = (duk_hcompfunc *) DUK_TVAL_GET_OBJECT(tv);
44707 			DUK_ASSERT(fun != NULL);
44708 		} else if (DUK_TVAL_IS_NUMBER(tv)) {
44709 			level = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv);
44710 		} else {
44711 			DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!T", tv));
44712 			goto fail_args;
44713 		}
44714 	}
44715 
44716 	if (fun == NULL) {
44717 		act = duk_hthread_get_activation_for_level(thr, level);
44718 		if (act == NULL) {
44719 			goto fail_index;
44720 		}
44721 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
44722 	}
44723 
44724 	if (fun == NULL || !DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)) {
44725 		DUK_D(DUK_DPRINT("invalid argument to GetBytecode: %!O", fun));
44726 		goto fail_args;
44727 	}
44728 	DUK_ASSERT(fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun));
44729 
44730 	duk_debug_write_reply(thr);
44731 	n = DUK_HCOMPFUNC_GET_CONSTS_COUNT(heap, fun);
44732 	duk_debug_write_int(thr, (duk_int32_t) n);
44733 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, fun);
44734 	for (i = 0; i < n; i++) {
44735 		duk_debug_write_tval(thr, tv);
44736 		tv++;
44737 	}
44738 	n = DUK_HCOMPFUNC_GET_FUNCS_COUNT(heap, fun);
44739 	duk_debug_write_int(thr, (duk_int32_t) n);
44740 	fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, fun);
44741 	for (i = 0; i < n; i++) {
44742 		duk_debug_write_hobject(thr, *fn);
44743 		fn++;
44744 	}
44745 	duk_debug_write_string(thr,
44746 	                       (const char *) DUK_HCOMPFUNC_GET_CODE_BASE(heap, fun),
44747 	                       (duk_size_t) DUK_HCOMPFUNC_GET_CODE_SIZE(heap, fun));
44748 	duk_debug_write_eom(thr);
44749 	return;
44750 
44751  fail_args:
44752 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid argument");
44753 	return;
44754 
44755  fail_index:
44756 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "invalid callstack index");
44757 	return;
44758 }
44759 
44760 /*
44761  *  Object inspection commands: GetHeapObjInfo, GetObjPropDesc,
44762  *  GetObjPropDescRange
44763  */
44764 
44765 #if defined(DUK_USE_DEBUGGER_INSPECT)
44766 
44767 #if 0 /* pruned */
44768 DUK_LOCAL const char * const duk__debug_getinfo_heaphdr_keys[] = {
44769 	"reachable",
44770 	"temproot",
44771 	"finalizable",
44772 	"finalized",
44773 	"readonly"
44774 	/* NULL not needed here */
44775 };
44776 DUK_LOCAL duk_uint_t duk__debug_getinfo_heaphdr_masks[] = {
44777 	DUK_HEAPHDR_FLAG_REACHABLE,
44778 	DUK_HEAPHDR_FLAG_TEMPROOT,
44779 	DUK_HEAPHDR_FLAG_FINALIZABLE,
44780 	DUK_HEAPHDR_FLAG_FINALIZED,
44781 	DUK_HEAPHDR_FLAG_READONLY,
44782 	0  /* terminator */
44783 };
44784 #endif
44785 DUK_LOCAL const char * const duk__debug_getinfo_hstring_keys[] = {
44786 #if 0
44787 	"arridx",
44788 	"symbol",
44789 	"hidden",
44790 	"reserved_word",
44791 	"strict_reserved_word",
44792 	"eval_or_arguments",
44793 #endif
44794 	"extdata"
44795 	/* NULL not needed here */
44796 };
44797 DUK_LOCAL duk_uint_t duk__debug_getinfo_hstring_masks[] = {
44798 #if 0
44799 	DUK_HSTRING_FLAG_ARRIDX,
44800 	DUK_HSTRING_FLAG_SYMBOL,
44801 	DUK_HSTRING_FLAG_HIDDEN,
44802 	DUK_HSTRING_FLAG_RESERVED_WORD,
44803 	DUK_HSTRING_FLAG_STRICT_RESERVED_WORD,
44804 	DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS,
44805 #endif
44806 	DUK_HSTRING_FLAG_EXTDATA,
44807 	0  /* terminator */
44808 };
44809 DUK_LOCAL const char * const duk__debug_getinfo_hobject_keys[] = {
44810 	"extensible",
44811 	"constructable",
44812 	"callable",
44813 	"boundfunc",
44814 	"compfunc",
44815 	"natfunc",
44816 	"bufobj",
44817 	"fastrefs",
44818 	"array_part",
44819 	"strict",
44820 	"notail",
44821 	"newenv",
44822 	"namebinding",
44823 	"createargs",
44824 	"have_finalizer",
44825 	"exotic_array",
44826 	"exotic_stringobj",
44827 	"exotic_arguments",
44828 	"exotic_proxyobj",
44829 	"special_call"
44830 	/* NULL not needed here */
44831 };
44832 DUK_LOCAL duk_uint_t duk__debug_getinfo_hobject_masks[] = {
44833 	DUK_HOBJECT_FLAG_EXTENSIBLE,
44834 	DUK_HOBJECT_FLAG_CONSTRUCTABLE,
44835 	DUK_HOBJECT_FLAG_CALLABLE,
44836 	DUK_HOBJECT_FLAG_BOUNDFUNC,
44837 	DUK_HOBJECT_FLAG_COMPFUNC,
44838 	DUK_HOBJECT_FLAG_NATFUNC,
44839 	DUK_HOBJECT_FLAG_BUFOBJ,
44840 	DUK_HOBJECT_FLAG_FASTREFS,
44841 	DUK_HOBJECT_FLAG_ARRAY_PART,
44842 	DUK_HOBJECT_FLAG_STRICT,
44843 	DUK_HOBJECT_FLAG_NOTAIL,
44844 	DUK_HOBJECT_FLAG_NEWENV,
44845 	DUK_HOBJECT_FLAG_NAMEBINDING,
44846 	DUK_HOBJECT_FLAG_CREATEARGS,
44847 	DUK_HOBJECT_FLAG_HAVE_FINALIZER,
44848 	DUK_HOBJECT_FLAG_EXOTIC_ARRAY,
44849 	DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ,
44850 	DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS,
44851 	DUK_HOBJECT_FLAG_EXOTIC_PROXYOBJ,
44852 	DUK_HOBJECT_FLAG_SPECIAL_CALL,
44853 	0  /* terminator */
44854 };
44855 DUK_LOCAL const char * const duk__debug_getinfo_hbuffer_keys[] = {
44856 	"dynamic",
44857 	"external"
44858 	/* NULL not needed here */
44859 };
44860 DUK_LOCAL duk_uint_t duk__debug_getinfo_hbuffer_masks[] = {
44861 	DUK_HBUFFER_FLAG_DYNAMIC,
44862 	DUK_HBUFFER_FLAG_EXTERNAL,
44863 	0  /* terminator */
44864 };
44865 
44866 DUK_LOCAL void duk__debug_getinfo_flags_key(duk_hthread *thr, const char *key) {
44867 	duk_debug_write_uint(thr, 0);
44868 	duk_debug_write_cstring(thr, key);
44869 }
44870 
44871 DUK_LOCAL void duk__debug_getinfo_prop_uint(duk_hthread *thr, const char *key, duk_uint_t val) {
44872 	duk_debug_write_uint(thr, 0);
44873 	duk_debug_write_cstring(thr, key);
44874 	duk_debug_write_uint(thr, val);
44875 }
44876 
44877 DUK_LOCAL void duk__debug_getinfo_prop_int(duk_hthread *thr, const char *key, duk_int_t val) {
44878 	duk_debug_write_uint(thr, 0);
44879 	duk_debug_write_cstring(thr, key);
44880 	duk_debug_write_int(thr, val);
44881 }
44882 
44883 DUK_LOCAL void duk__debug_getinfo_prop_bool(duk_hthread *thr, const char *key, duk_bool_t val) {
44884 	duk_debug_write_uint(thr, 0);
44885 	duk_debug_write_cstring(thr, key);
44886 	duk_debug_write_boolean(thr, val);
44887 }
44888 
44889 DUK_LOCAL void duk__debug_getinfo_bitmask(duk_hthread *thr, const char * const * keys, duk_uint_t *masks, duk_uint_t flags) {
44890 	const char *key;
44891 	duk_uint_t mask;
44892 
44893 	for (;;) {
44894 		mask = *masks++;
44895 		if (mask == 0) {
44896 			break;
44897 		}
44898 		key = *keys++;
44899 		DUK_ASSERT(key != NULL);
44900 
44901 		DUK_DD(DUK_DDPRINT("inspect bitmask: key=%s, mask=0x%08lx, flags=0x%08lx", key, (unsigned long) mask, (unsigned long) flags));
44902 		duk__debug_getinfo_prop_bool(thr, key, flags & mask);
44903 	}
44904 }
44905 
44906 /* Inspect a property using a virtual index into a conceptual property list
44907  * consisting of (1) all array part items from [0,a_size[ (even when above
44908  * .length) and (2) all entry part items from [0,e_next[.  Unused slots are
44909  * indicated using dvalue 'unused'.
44910  */
44911 DUK_LOCAL duk_bool_t duk__debug_getprop_index(duk_hthread *thr, duk_heap *heap, duk_hobject *h_obj, duk_uint_t idx) {
44912 	duk_uint_t a_size;
44913 	duk_tval *tv;
44914 	duk_hstring *h_key;
44915 	duk_hobject *h_getset;
44916 	duk_uint_t flags;
44917 
44918 	DUK_UNREF(heap);
44919 
44920 	a_size = DUK_HOBJECT_GET_ASIZE(h_obj);
44921 	if (idx < a_size) {
44922 		duk_debug_write_uint(thr, DUK_PROPDESC_FLAGS_WEC);
44923 		duk_debug_write_uint(thr, idx);
44924 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, h_obj, idx);
44925 		duk_debug_write_tval(thr, tv);
44926 		return 1;
44927 	}
44928 
44929 	idx -= a_size;
44930 	if (idx >= DUK_HOBJECT_GET_ENEXT(h_obj)) {
44931 		return 0;
44932 	}
44933 
44934 	h_key = DUK_HOBJECT_E_GET_KEY(heap, h_obj, idx);
44935 	if (h_key == NULL) {
44936 		duk_debug_write_uint(thr, 0);
44937 		duk_debug_write_null(thr);
44938 		duk_debug_write_unused(thr);
44939 		return 1;
44940 	}
44941 
44942 	flags = DUK_HOBJECT_E_GET_FLAGS(heap, h_obj, idx);
44943 	if (DUK_HSTRING_HAS_SYMBOL(h_key)) {
44944 		flags |= DUK_DBG_PROPFLAG_SYMBOL;
44945 	}
44946 	if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
44947 		flags |= DUK_DBG_PROPFLAG_HIDDEN;
44948 	}
44949 	duk_debug_write_uint(thr, flags);
44950 	duk_debug_write_hstring(thr, h_key);
44951 	if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
44952 		h_getset = DUK_HOBJECT_E_GET_VALUE_GETTER(heap, h_obj, idx);
44953 		if (h_getset) {
44954 			duk_debug_write_hobject(thr, h_getset);
44955 		} else {
44956 			duk_debug_write_null(thr);
44957 		}
44958 		h_getset = DUK_HOBJECT_E_GET_VALUE_SETTER(heap, h_obj, idx);
44959 		if (h_getset) {
44960 			duk_debug_write_hobject(thr, h_getset);
44961 		} else {
44962 			duk_debug_write_null(thr);
44963 		}
44964 	} else {
44965 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, h_obj, idx);
44966 		duk_debug_write_tval(thr, tv);
44967 	}
44968 	return 1;
44969 }
44970 
44971 DUK_LOCAL void duk__debug_handle_get_heap_obj_info(duk_hthread *thr, duk_heap *heap) {
44972 	duk_heaphdr *h;
44973 
44974 	DUK_D(DUK_DPRINT("debug command GetHeapObjInfo"));
44975 	DUK_UNREF(heap);
44976 
44977 	DUK_ASSERT(sizeof(duk__debug_getinfo_hstring_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hstring_masks) / sizeof(duk_uint_t) - 1);
44978 	DUK_ASSERT(sizeof(duk__debug_getinfo_hobject_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hobject_masks) / sizeof(duk_uint_t) - 1);
44979 	DUK_ASSERT(sizeof(duk__debug_getinfo_hbuffer_keys) / sizeof(const char *) == sizeof(duk__debug_getinfo_hbuffer_masks) / sizeof(duk_uint_t) - 1);
44980 
44981 	h = duk_debug_read_any_ptr(thr);
44982 	if (!h) {
44983 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
44984 		return;
44985 	}
44986 
44987 	duk_debug_write_reply(thr);
44988 
44989 	/* As with all inspection code, we rely on the debug client providing
44990 	 * a valid, non-stale pointer: there's no portable way to safely
44991 	 * validate the pointer here.
44992 	 */
44993 
44994 	duk__debug_getinfo_flags_key(thr, "heapptr");
44995 	duk_debug_write_heapptr(thr, h);
44996 
44997 	/* XXX: comes out as signed now */
44998 	duk__debug_getinfo_prop_uint(thr, "heaphdr_flags", (duk_uint_t) DUK_HEAPHDR_GET_FLAGS(h));
44999 	duk__debug_getinfo_prop_uint(thr, "heaphdr_type", (duk_uint_t) DUK_HEAPHDR_GET_TYPE(h));
45000 #if defined(DUK_USE_REFERENCE_COUNTING)
45001 	duk__debug_getinfo_prop_uint(thr, "refcount", (duk_uint_t) DUK_HEAPHDR_GET_REFCOUNT(h));
45002 #endif
45003 #if 0 /* pruned */
45004 	duk__debug_getinfo_bitmask(thr,
45005 	                           duk__debug_getinfo_heaphdr_keys,
45006 	                           duk__debug_getinfo_heaphdr_masks,
45007 	                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45008 #endif
45009 
45010 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
45011 	case DUK_HTYPE_STRING: {
45012 		duk_hstring *h_str;
45013 
45014 		h_str = (duk_hstring *) h;
45015 		duk__debug_getinfo_bitmask(thr,
45016 		                           duk__debug_getinfo_hstring_keys,
45017 		                           duk__debug_getinfo_hstring_masks,
45018 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45019 		duk__debug_getinfo_prop_uint(thr, "bytelen", (duk_uint_t) DUK_HSTRING_GET_BYTELEN(h_str));
45020 		duk__debug_getinfo_prop_uint(thr, "charlen", (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_str));
45021 		duk__debug_getinfo_prop_uint(thr, "hash", (duk_uint_t) DUK_HSTRING_GET_HASH(h_str));
45022 		duk__debug_getinfo_flags_key(thr, "data");
45023 		duk_debug_write_hstring(thr, h_str);
45024 		break;
45025 	}
45026 	case DUK_HTYPE_OBJECT: {
45027 		duk_hobject *h_obj;
45028 		duk_hobject *h_proto;
45029 
45030 		h_obj = (duk_hobject *) h;
45031 		h_proto = DUK_HOBJECT_GET_PROTOTYPE(heap, h_obj);
45032 
45033 		/* duk_hobject specific fields. */
45034 		duk__debug_getinfo_bitmask(thr,
45035 		                           duk__debug_getinfo_hobject_keys,
45036 		                           duk__debug_getinfo_hobject_masks,
45037 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45038 		duk__debug_getinfo_prop_uint(thr, "class_number", DUK_HOBJECT_GET_CLASS_NUMBER(h_obj));
45039 		duk__debug_getinfo_flags_key(thr, "class_name");
45040 		duk_debug_write_hstring(thr, DUK_HOBJECT_GET_CLASS_STRING(heap, h_obj));
45041 		duk__debug_getinfo_flags_key(thr, "prototype");
45042 		if (h_proto != NULL) {
45043 			duk_debug_write_hobject(thr, h_proto);
45044 		} else {
45045 			duk_debug_write_null(thr);
45046 		}
45047 		duk__debug_getinfo_flags_key(thr, "props");
45048 		duk_debug_write_pointer(thr, (void *) DUK_HOBJECT_GET_PROPS(heap, h_obj));
45049 		duk__debug_getinfo_prop_uint(thr, "e_size", (duk_uint_t) DUK_HOBJECT_GET_ESIZE(h_obj));
45050 		duk__debug_getinfo_prop_uint(thr, "e_next", (duk_uint_t) DUK_HOBJECT_GET_ENEXT(h_obj));
45051 		duk__debug_getinfo_prop_uint(thr, "a_size", (duk_uint_t) DUK_HOBJECT_GET_ASIZE(h_obj));
45052 		duk__debug_getinfo_prop_uint(thr, "h_size", (duk_uint_t) DUK_HOBJECT_GET_HSIZE(h_obj));
45053 
45054 		if (DUK_HOBJECT_IS_ARRAY(h_obj)) {
45055 			duk_harray *h_arr;
45056 			h_arr = (duk_harray *) h_obj;
45057 
45058 			duk__debug_getinfo_prop_uint(thr, "length", (duk_uint_t) h_arr->length);
45059 			duk__debug_getinfo_prop_bool(thr, "length_nonwritable", h_arr->length_nonwritable);
45060 		}
45061 
45062 		if (DUK_HOBJECT_IS_NATFUNC(h_obj)) {
45063 			duk_hnatfunc *h_fun;
45064 			h_fun = (duk_hnatfunc *) h_obj;
45065 
45066 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45067 			duk__debug_getinfo_prop_int(thr, "magic", h_fun->magic);
45068 			duk__debug_getinfo_prop_bool(thr, "varargs", h_fun->magic == DUK_HNATFUNC_NARGS_VARARGS);
45069 			/* Native function pointer may be different from a void pointer,
45070 			 * and we serialize it from memory directly now (no byte swapping etc).
45071 			 */
45072 			duk__debug_getinfo_flags_key(thr, "funcptr");
45073 			duk_debug_write_buffer(thr, (const char *) &h_fun->func, sizeof(h_fun->func));
45074 		}
45075 
45076 		if (DUK_HOBJECT_IS_COMPFUNC(h_obj)) {
45077 			duk_hcompfunc *h_fun;
45078 			duk_hbuffer *h_buf;
45079 			duk_hobject *h_lexenv;
45080 			duk_hobject *h_varenv;
45081 			h_fun = (duk_hcompfunc *) h_obj;
45082 
45083 			duk__debug_getinfo_prop_int(thr, "nregs", h_fun->nregs);
45084 			duk__debug_getinfo_prop_int(thr, "nargs", h_fun->nargs);
45085 
45086 			duk__debug_getinfo_flags_key(thr, "lex_env");
45087 			h_lexenv = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, h_fun);
45088 			if (h_lexenv != NULL) {
45089 				duk_debug_write_hobject(thr, h_lexenv);
45090 			} else {
45091 				duk_debug_write_null(thr);
45092 			}
45093 			duk__debug_getinfo_flags_key(thr, "var_env");
45094 			h_varenv = DUK_HCOMPFUNC_GET_VARENV(thr->heap, h_fun);
45095 			if (h_varenv != NULL) {
45096 				duk_debug_write_hobject(thr, h_varenv);
45097 			} else {
45098 				duk_debug_write_null(thr);
45099 			}
45100 
45101 			duk__debug_getinfo_prop_uint(thr, "start_line", h_fun->start_line);
45102 			duk__debug_getinfo_prop_uint(thr, "end_line", h_fun->end_line);
45103 			h_buf = (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(thr->heap, h_fun);
45104 			if (h_buf != NULL) {
45105 				duk__debug_getinfo_flags_key(thr, "data");
45106 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_buf);
45107 			}
45108 		}
45109 
45110 		if (DUK_HOBJECT_IS_BOUNDFUNC(h_obj)) {
45111 			duk_hboundfunc *h_bfun;
45112 			h_bfun = (duk_hboundfunc *) (void *) h_obj;
45113 
45114 			duk__debug_getinfo_flags_key(thr, "target");
45115 			duk_debug_write_tval(thr, &h_bfun->target);
45116 			duk__debug_getinfo_flags_key(thr, "this_binding");
45117 			duk_debug_write_tval(thr, &h_bfun->this_binding);
45118 			duk__debug_getinfo_flags_key(thr, "nargs");
45119 			duk_debug_write_int(thr, h_bfun->nargs);
45120 			/* h_bfun->args not exposed now */
45121 		}
45122 
45123 		if (DUK_HOBJECT_IS_THREAD(h_obj)) {
45124 			/* XXX: Currently no inspection of threads, e.g. value stack, call
45125 			 * stack, catch stack, etc.
45126 			 */
45127 			duk_hthread *h_thr;
45128 			h_thr = (duk_hthread *) h_obj;
45129 			DUK_UNREF(h_thr);
45130 		}
45131 
45132 		if (DUK_HOBJECT_IS_DECENV(h_obj)) {
45133 			duk_hdecenv *h_env;
45134 			h_env = (duk_hdecenv *) h_obj;
45135 
45136 			duk__debug_getinfo_flags_key(thr, "thread");
45137 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->thread));
45138 			duk__debug_getinfo_flags_key(thr, "varmap");
45139 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->varmap));
45140 			duk__debug_getinfo_prop_uint(thr, "regbase", (duk_uint_t) h_env->regbase_byteoff);
45141 		}
45142 
45143 		if (DUK_HOBJECT_IS_OBJENV(h_obj)) {
45144 			duk_hobjenv *h_env;
45145 			h_env = (duk_hobjenv *) h_obj;
45146 
45147 			duk__debug_getinfo_flags_key(thr, "target");
45148 			duk_debug_write_heapptr(thr, (duk_heaphdr *) (h_env->target));
45149 			duk__debug_getinfo_prop_bool(thr, "has_this", h_env->has_this);
45150 		}
45151 
45152 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
45153 		if (DUK_HOBJECT_IS_BUFOBJ(h_obj)) {
45154 			duk_hbufobj *h_bufobj;
45155 			h_bufobj = (duk_hbufobj *) h_obj;
45156 
45157 			duk__debug_getinfo_prop_uint(thr, "slice_offset", h_bufobj->offset);
45158 			duk__debug_getinfo_prop_uint(thr, "slice_length", h_bufobj->length);
45159 			duk__debug_getinfo_prop_uint(thr, "elem_shift", (duk_uint_t) h_bufobj->shift);
45160 			duk__debug_getinfo_prop_uint(thr, "elem_type", (duk_uint_t) h_bufobj->elem_type);
45161 			duk__debug_getinfo_prop_bool(thr, "is_typedarray", (duk_uint_t) h_bufobj->is_typedarray);
45162 			if (h_bufobj->buf != NULL) {
45163 				duk__debug_getinfo_flags_key(thr, "buffer");
45164 				duk_debug_write_heapptr(thr, (duk_heaphdr *) h_bufobj->buf);
45165 			}
45166 		}
45167 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
45168 		break;
45169 	}
45170 	case DUK_HTYPE_BUFFER: {
45171 		duk_hbuffer *h_buf;
45172 
45173 		h_buf = (duk_hbuffer *) h;
45174 		duk__debug_getinfo_bitmask(thr,
45175 		                           duk__debug_getinfo_hbuffer_keys,
45176 		                           duk__debug_getinfo_hbuffer_masks,
45177 		                           DUK_HEAPHDR_GET_FLAGS_RAW(h));
45178 		duk__debug_getinfo_prop_uint(thr, "size", (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_buf));
45179 		duk__debug_getinfo_flags_key(thr, "dataptr");
45180 		duk_debug_write_pointer(thr, (void *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_buf));
45181 		duk__debug_getinfo_flags_key(thr, "data");
45182 		duk_debug_write_hbuffer(thr, h_buf);  /* tolerates NULL h_buf */
45183 		break;
45184 	}
45185 	default: {
45186 		/* Since we already started writing the reply, just emit nothing. */
45187 		DUK_D(DUK_DPRINT("inspect target pointer has invalid heaphdr type"));
45188 	}
45189 	}
45190 
45191 	duk_debug_write_eom(thr);
45192 }
45193 
45194 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc(duk_hthread *thr, duk_heap *heap) {
45195 	duk_heaphdr *h;
45196 	duk_hobject *h_obj;
45197 	duk_hstring *h_key;
45198 	duk_propdesc desc;
45199 
45200 	DUK_D(DUK_DPRINT("debug command GetObjPropDesc"));
45201 	DUK_UNREF(heap);
45202 
45203 	h = duk_debug_read_any_ptr(thr);
45204 	if (!h) {
45205 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid target");
45206 		return;
45207 	}
45208 	h_key = duk_debug_read_hstring(thr);
45209 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT || h_key == NULL) {
45210 		goto fail_args;
45211 	}
45212 	h_obj = (duk_hobject *) h;
45213 
45214 	if (duk_hobject_get_own_propdesc(thr, h_obj, h_key, &desc, 0 /*flags*/)) {
45215 		duk_int_t virtual_idx;
45216 		duk_bool_t rc;
45217 
45218 		/* To use the shared helper need the virtual index. */
45219 		DUK_ASSERT(desc.e_idx >= 0 || desc.a_idx >= 0);
45220 		virtual_idx = (desc.a_idx >= 0 ? desc.a_idx :
45221 		               (duk_int_t) DUK_HOBJECT_GET_ASIZE(h_obj) + desc.e_idx);
45222 
45223 		duk_debug_write_reply(thr);
45224 		rc = duk__debug_getprop_index(thr, heap, h_obj, (duk_uint_t) virtual_idx);
45225 		DUK_ASSERT(rc == 1);
45226 		DUK_UNREF(rc);
45227 		duk_debug_write_eom(thr);
45228 	} else {
45229 		duk_debug_write_error_eom(thr, DUK_DBG_ERR_NOTFOUND, "not found");
45230 	}
45231 	return;
45232 
45233  fail_args:
45234 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45235 }
45236 
45237 DUK_LOCAL void duk__debug_handle_get_obj_prop_desc_range(duk_hthread *thr, duk_heap *heap) {
45238 	duk_heaphdr *h;
45239 	duk_hobject *h_obj;
45240 	duk_uint_t idx, idx_start, idx_end;
45241 
45242 	DUK_D(DUK_DPRINT("debug command GetObjPropDescRange"));
45243 	DUK_UNREF(heap);
45244 
45245 	h = duk_debug_read_any_ptr(thr);
45246 	idx_start = (duk_uint_t) duk_debug_read_int(thr);
45247 	idx_end = (duk_uint_t) duk_debug_read_int(thr);
45248 	if (h == NULL || DUK_HEAPHDR_GET_TYPE(h) != DUK_HTYPE_OBJECT) {
45249 		goto fail_args;
45250 	}
45251 	h_obj = (duk_hobject *) h;
45252 
45253 	/* The index range space is conceptually the array part followed by the
45254 	 * entry part.  Unlike normal enumeration all slots are exposed here as
45255 	 * is and return 'unused' if the slots are not in active use.  In particular
45256 	 * the array part is included for the full a_size regardless of what the
45257 	 * array .length is.
45258 	 */
45259 
45260 	duk_debug_write_reply(thr);
45261 	for (idx = idx_start; idx < idx_end; idx++) {
45262 		if (!duk__debug_getprop_index(thr, heap, h_obj, idx)) {
45263 			break;
45264 		}
45265 	}
45266 	duk_debug_write_eom(thr);
45267 	return;
45268 
45269  fail_args:
45270 	duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNKNOWN, "invalid args");
45271 }
45272 
45273 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45274 
45275 /*
45276  *  Process incoming debug requests
45277  *
45278  *  Individual request handlers can push temporaries on the value stack and
45279  *  rely on duk__debug_process_message() to restore the value stack top
45280  *  automatically.
45281  */
45282 
45283 /* Process one debug message.  Automatically restore value stack top to its
45284  * entry value, so that individual message handlers don't need exact value
45285  * stack handling which is convenient.
45286  */
45287 DUK_LOCAL void duk__debug_process_message(duk_hthread *thr) {
45288 	duk_heap *heap;
45289 	duk_uint8_t x;
45290 	duk_int32_t cmd;
45291 	duk_idx_t entry_top;
45292 
45293 	DUK_ASSERT(thr != NULL);
45294 	heap = thr->heap;
45295 	DUK_ASSERT(heap != NULL);
45296 
45297 	entry_top = duk_get_top(thr);
45298 
45299 	x = duk_debug_read_byte(thr);
45300 	switch (x) {
45301 	case DUK_DBG_IB_REQUEST: {
45302 		cmd = duk_debug_read_int(thr);
45303 		switch (cmd) {
45304 		case DUK_DBG_CMD_BASICINFO: {
45305 			duk__debug_handle_basic_info(thr, heap);
45306 			break;
45307 		}
45308 		case DUK_DBG_CMD_TRIGGERSTATUS: {
45309 			duk__debug_handle_trigger_status(thr, heap);
45310 			break;
45311 		}
45312 		case DUK_DBG_CMD_PAUSE: {
45313 			duk__debug_handle_pause(thr, heap);
45314 			break;
45315 		}
45316 		case DUK_DBG_CMD_RESUME: {
45317 			duk__debug_handle_resume(thr, heap);
45318 			break;
45319 		}
45320 		case DUK_DBG_CMD_STEPINTO:
45321 		case DUK_DBG_CMD_STEPOVER:
45322 		case DUK_DBG_CMD_STEPOUT: {
45323 			duk__debug_handle_step(thr, heap, cmd);
45324 			break;
45325 		}
45326 		case DUK_DBG_CMD_LISTBREAK: {
45327 			duk__debug_handle_list_break(thr, heap);
45328 			break;
45329 		}
45330 		case DUK_DBG_CMD_ADDBREAK: {
45331 			duk__debug_handle_add_break(thr, heap);
45332 			break;
45333 		}
45334 		case DUK_DBG_CMD_DELBREAK: {
45335 			duk__debug_handle_del_break(thr, heap);
45336 			break;
45337 		}
45338 		case DUK_DBG_CMD_GETVAR: {
45339 			duk__debug_handle_get_var(thr, heap);
45340 			break;
45341 		}
45342 		case DUK_DBG_CMD_PUTVAR: {
45343 			duk__debug_handle_put_var(thr, heap);
45344 			break;
45345 		}
45346 		case DUK_DBG_CMD_GETCALLSTACK: {
45347 			duk__debug_handle_get_call_stack(thr, heap);
45348 			break;
45349 		}
45350 		case DUK_DBG_CMD_GETLOCALS: {
45351 			duk__debug_handle_get_locals(thr, heap);
45352 			break;
45353 		}
45354 		case DUK_DBG_CMD_EVAL: {
45355 			duk__debug_handle_eval(thr, heap);
45356 			break;
45357 		}
45358 		case DUK_DBG_CMD_DETACH: {
45359 			/* The actual detached_cb call is postponed to message loop so
45360 			 * we don't need any special precautions here (just skip to EOM
45361 			 * on the already closed connection).
45362 			 */
45363 			duk__debug_handle_detach(thr, heap);
45364 			break;
45365 		}
45366 #if defined(DUK_USE_DEBUGGER_DUMPHEAP)
45367 		case DUK_DBG_CMD_DUMPHEAP: {
45368 			duk__debug_handle_dump_heap(thr, heap);
45369 			break;
45370 		}
45371 #endif  /* DUK_USE_DEBUGGER_DUMPHEAP */
45372 		case DUK_DBG_CMD_GETBYTECODE: {
45373 			duk__debug_handle_get_bytecode(thr, heap);
45374 			break;
45375 		}
45376 		case DUK_DBG_CMD_APPREQUEST: {
45377 			duk__debug_handle_apprequest(thr, heap);
45378 			break;
45379 		}
45380 #if defined(DUK_USE_DEBUGGER_INSPECT)
45381 		case DUK_DBG_CMD_GETHEAPOBJINFO: {
45382 			duk__debug_handle_get_heap_obj_info(thr, heap);
45383 			break;
45384 		}
45385 		case DUK_DBG_CMD_GETOBJPROPDESC: {
45386 			duk__debug_handle_get_obj_prop_desc(thr, heap);
45387 			break;
45388 		}
45389 		case DUK_DBG_CMD_GETOBJPROPDESCRANGE: {
45390 			duk__debug_handle_get_obj_prop_desc_range(thr, heap);
45391 			break;
45392 		}
45393 #endif  /* DUK_USE_DEBUGGER_INSPECT */
45394 		default: {
45395 			DUK_D(DUK_DPRINT("debug command unsupported: %d", (int) cmd));
45396 			duk_debug_write_error_eom(thr, DUK_DBG_ERR_UNSUPPORTED, "unsupported command");
45397 		}
45398 		}  /* switch cmd */
45399 		break;
45400 	}
45401 	case DUK_DBG_IB_REPLY: {
45402 		DUK_D(DUK_DPRINT("debug reply, skipping"));
45403 		break;
45404 	}
45405 	case DUK_DBG_IB_ERROR: {
45406 		DUK_D(DUK_DPRINT("debug error, skipping"));
45407 		break;
45408 	}
45409 	case DUK_DBG_IB_NOTIFY: {
45410 		DUK_D(DUK_DPRINT("debug notify, skipping"));
45411 		break;
45412 	}
45413 	default: {
45414 		DUK_D(DUK_DPRINT("invalid initial byte, drop connection: %d", (int) x));
45415 		goto fail;
45416 	}
45417 	}  /* switch initial byte */
45418 
45419 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45420 	duk_set_top(thr, entry_top);
45421 	duk__debug_skip_to_eom(thr);
45422 	return;
45423 
45424  fail:
45425 	DUK_ASSERT(duk_get_top(thr) >= entry_top);
45426 	duk_set_top(thr, entry_top);
45427 	DUK__SET_CONN_BROKEN(thr, 1);
45428 	return;
45429 }
45430 
45431 DUK_LOCAL void duk__check_resend_status(duk_hthread *thr) {
45432 	if (thr->heap->dbg_read_cb != NULL && thr->heap->dbg_state_dirty) {
45433 		duk_debug_send_status(thr);
45434 		thr->heap->dbg_state_dirty = 0;
45435 	}
45436 }
45437 
45438 DUK_INTERNAL duk_bool_t duk_debug_process_messages(duk_hthread *thr, duk_bool_t no_block) {
45439 #if defined(DUK_USE_ASSERTIONS)
45440 	duk_idx_t entry_top;
45441 #endif
45442 	duk_bool_t retval = 0;
45443 
45444 	DUK_ASSERT(thr != NULL);
45445 	DUK_ASSERT(thr->heap != NULL);
45446 #if defined(DUK_USE_ASSERTIONS)
45447 	entry_top = duk_get_top(thr);
45448 #endif
45449 
45450 	DUK_D(DUK_DPRINT("process debug messages: read_cb=%s, no_block=%ld, detaching=%ld, processing=%ld",
45451 	                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) no_block,
45452 	                 (long) thr->heap->dbg_detaching, (long) thr->heap->dbg_processing));
45453 	DUK_DD(DUK_DDPRINT("top at entry: %ld", (long) duk_get_top(thr)));
45454 
45455 	/* thr->heap->dbg_detaching may be != 0 if a debugger write outside
45456 	 * the message loop caused a transport error and detach1() to run.
45457 	 */
45458 	DUK_ASSERT(thr->heap->dbg_detaching == 0 || thr->heap->dbg_detaching == 1);
45459 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45460 	thr->heap->dbg_processing = 1;
45461 
45462 	/* Ensure dirty state causes a Status even if never process any
45463 	 * messages.  This is expected by the bytecode executor when in
45464 	 * the running state.
45465 	 */
45466 	duk__check_resend_status(thr);
45467 
45468 	for (;;) {
45469 		/* Process messages until we're no longer paused or we peek
45470 		 * and see there's nothing to read right now.
45471 		 */
45472 		DUK_DD(DUK_DDPRINT("top at loop top: %ld", (long) duk_get_top(thr)));
45473 		DUK_ASSERT(thr->heap->dbg_processing == 1);
45474 
45475 		while (thr->heap->dbg_read_cb == NULL && thr->heap->dbg_detaching) {
45476 			/* Detach is pending; can be triggered from outside the
45477 			 * debugger loop (e.g. Status notify write error) or by
45478 			 * previous message handling.  Call detached callback
45479 			 * here, in a controlled state, to ensure a possible
45480 			 * reattach inside the detached_cb is handled correctly.
45481 			 *
45482 			 * Recheck for detach in a while loop: an immediate
45483 			 * reattach involves a call to duk_debugger_attach()
45484 			 * which writes a debugger handshake line immediately
45485 			 * inside the API call.  If the transport write fails
45486 			 * for that handshake, we can immediately end up in a
45487 			 * "transport broken, detaching" case several times here.
45488 			 * Loop back until we're either cleanly attached or
45489 			 * fully detached.
45490 			 *
45491 			 * NOTE: Reset dbg_processing = 1 forcibly, in case we
45492 			 * re-attached; duk_debugger_attach() sets dbg_processing
45493 			 * to 0 at the moment.
45494 			 */
45495 
45496 			DUK_D(DUK_DPRINT("detach pending (dbg_read_cb == NULL, dbg_detaching != 0), call detach2"));
45497 
45498 			duk__debug_do_detach2(thr->heap);
45499 			thr->heap->dbg_processing = 1;  /* may be set to 0 by duk_debugger_attach() inside callback */
45500 
45501 			DUK_D(DUK_DPRINT("after detach2 (and possible reattach): dbg_read_cb=%s, dbg_detaching=%ld",
45502 			                 thr->heap->dbg_read_cb ? "not NULL" : "NULL", (long) thr->heap->dbg_detaching));
45503 		}
45504 		DUK_ASSERT(thr->heap->dbg_detaching == 0);  /* true even with reattach */
45505 		DUK_ASSERT(thr->heap->dbg_processing == 1);  /* even after a detach and possible reattach */
45506 
45507 		if (thr->heap->dbg_read_cb == NULL) {
45508 			DUK_D(DUK_DPRINT("debug connection broken (and not detaching), stop processing messages"));
45509 			break;
45510 		}
45511 
45512 		if (!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || no_block) {
45513 			if (!duk_debug_read_peek(thr)) {
45514 				/* Note: peek cannot currently trigger a detach
45515 				 * so the dbg_detaching == 0 assert outside the
45516 				 * loop is correct.
45517 				 */
45518 				DUK_D(DUK_DPRINT("processing debug message, peek indicated no data, stop processing messages"));
45519 				break;
45520 			}
45521 			DUK_D(DUK_DPRINT("processing debug message, peek indicated there is data, handle it"));
45522 		} else {
45523 			DUK_D(DUK_DPRINT("paused, process debug message, blocking if necessary"));
45524 		}
45525 
45526 		duk__check_resend_status(thr);
45527 		duk__debug_process_message(thr);
45528 		duk__check_resend_status(thr);
45529 
45530 		retval = 1;  /* processed one or more messages */
45531 	}
45532 
45533 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45534 	DUK_ASSERT(thr->heap->dbg_processing == 1);
45535 	thr->heap->dbg_processing = 0;
45536 
45537 	/* As an initial implementation, read flush after exiting the message
45538 	 * loop.  If transport is broken, this is a no-op (with debug logs).
45539 	 */
45540 	duk_debug_read_flush(thr);  /* this cannot initiate a detach */
45541 	DUK_ASSERT(thr->heap->dbg_detaching == 0);
45542 
45543 	DUK_DD(DUK_DDPRINT("top at exit: %ld", (long) duk_get_top(thr)));
45544 
45545 #if defined(DUK_USE_ASSERTIONS)
45546 	/* Easy to get wrong, so assert for it. */
45547 	DUK_ASSERT(entry_top == duk_get_top(thr));
45548 #endif
45549 
45550 	return retval;
45551 }
45552 
45553 /*
45554  *  Halt execution helper
45555  */
45556 
45557 /* Halt execution and enter a debugger message loop until execution is resumed
45558  * by the client.  PC for the current activation may be temporarily decremented
45559  * so that the "current" instruction will be shown by the client.  This helper
45560  * is callable from anywhere, also outside bytecode executor.
45561  */
45562 
45563 DUK_INTERNAL void duk_debug_halt_execution(duk_hthread *thr, duk_bool_t use_prev_pc) {
45564 	duk_activation *act;
45565 	duk_hcompfunc *fun;
45566 	duk_instr_t *old_pc = NULL;
45567 
45568 	DUK_ASSERT(thr != NULL);
45569 	DUK_ASSERT(thr->heap != NULL);
45570 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45571 	DUK_ASSERT(thr->heap->dbg_processing == 0);
45572 	DUK_ASSERT(!duk_debug_is_paused(thr->heap));
45573 
45574 	duk_debug_set_paused(thr->heap);
45575 
45576 	act = thr->callstack_curr;
45577 
45578 	/* NOTE: act may be NULL if an error is thrown outside of any activation,
45579 	 * which may happen in the case of, e.g. syntax errors.
45580 	 */
45581 
45582 	/* Decrement PC if that was requested, this requires a PC sync. */
45583 	if (act != NULL) {
45584 		duk_hthread_sync_currpc(thr);
45585 		old_pc = act->curr_pc;
45586 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
45587 
45588 		/* Short circuit if is safe: if act->curr_pc != NULL, 'fun' is
45589 		 * guaranteed to be a non-NULL ECMAScript function.
45590 		 */
45591 		DUK_ASSERT(act->curr_pc == NULL ||
45592 		           (fun != NULL && DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun)));
45593 		if (use_prev_pc &&
45594 		    act->curr_pc != NULL &&
45595 		    act->curr_pc > DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, fun)) {
45596 			act->curr_pc--;
45597 		}
45598 	}
45599 
45600 	/* Process debug messages until we are no longer paused. */
45601 
45602 	/* NOTE: This is a bit fragile.  It's important to ensure that
45603 	 * duk_debug_process_messages() never throws an error or
45604 	 * act->curr_pc will never be reset.
45605 	 */
45606 
45607 	thr->heap->dbg_state_dirty = 1;
45608 	while (DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
45609 		DUK_ASSERT(duk_debug_is_attached(thr->heap));
45610 		DUK_ASSERT(thr->heap->dbg_processing == 0);
45611 		duk_debug_process_messages(thr, 0 /*no_block*/);
45612 	}
45613 
45614 	/* XXX: Decrementing and restoring act->curr_pc works now, but if the
45615 	 * debugger message loop gains the ability to adjust the current PC
45616 	 * (e.g. a forced jump) restoring the PC here will break.  Another
45617 	 * approach would be to use a state flag for the "decrement 1 from
45618 	 * topmost activation's PC" and take it into account whenever dealing
45619 	 * with PC values.
45620 	 */
45621 	if (act != NULL) {
45622 		act->curr_pc = old_pc;  /* restore PC */
45623 	}
45624 }
45625 
45626 /*
45627  *  Breakpoint management
45628  */
45629 
45630 DUK_INTERNAL duk_small_int_t duk_debug_add_breakpoint(duk_hthread *thr, duk_hstring *filename, duk_uint32_t line) {
45631 	duk_heap *heap;
45632 	duk_breakpoint *b;
45633 
45634 	/* Caller must trigger recomputation of active breakpoint list.  To
45635 	 * ensure stale values are not used if that doesn't happen, clear the
45636 	 * active breakpoint list here.
45637 	 */
45638 
45639 	DUK_ASSERT(thr != NULL);
45640 	DUK_ASSERT(filename != NULL);
45641 	heap = thr->heap;
45642 	DUK_ASSERT(heap != NULL);
45643 
45644 	if (heap->dbg_breakpoint_count >= DUK_HEAP_MAX_BREAKPOINTS) {
45645 		DUK_D(DUK_DPRINT("failed to add breakpoint for %O:%ld, all breakpoint slots used",
45646 		                 (duk_heaphdr *) filename, (long) line));
45647 		return -1;
45648 	}
45649 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45650 	b = heap->dbg_breakpoints + (heap->dbg_breakpoint_count++);
45651 	b->filename = filename;
45652 	b->line = line;
45653 	DUK_HSTRING_INCREF(thr, filename);
45654 
45655 	return (duk_small_int_t) (heap->dbg_breakpoint_count - 1);  /* index */
45656 }
45657 
45658 DUK_INTERNAL duk_bool_t duk_debug_remove_breakpoint(duk_hthread *thr, duk_small_uint_t breakpoint_index) {
45659 	duk_heap *heap;
45660 	duk_hstring *h;
45661 	duk_breakpoint *b;
45662 	duk_size_t move_size;
45663 
45664 	/* Caller must trigger recomputation of active breakpoint list.  To
45665 	 * ensure stale values are not used if that doesn't happen, clear the
45666 	 * active breakpoint list here.
45667 	 */
45668 
45669 	DUK_ASSERT(thr != NULL);
45670 	heap = thr->heap;
45671 	DUK_ASSERT(heap != NULL);
45672 	DUK_ASSERT(duk_debug_is_attached(thr->heap));
45673 	DUK_ASSERT_DISABLE(breakpoint_index >= 0);  /* unsigned */
45674 
45675 	if (breakpoint_index >= heap->dbg_breakpoint_count) {
45676 		DUK_D(DUK_DPRINT("invalid breakpoint index: %ld", (long) breakpoint_index));
45677 		return 0;
45678 	}
45679 	b = heap->dbg_breakpoints + breakpoint_index;
45680 
45681 	h = b->filename;
45682 	DUK_ASSERT(h != NULL);
45683 
45684 	move_size = sizeof(duk_breakpoint) * (heap->dbg_breakpoint_count - breakpoint_index - 1);
45685 	duk_memmove((void *) b,
45686 	            (const void *) (b + 1),
45687 	            (size_t) move_size);
45688 
45689 	heap->dbg_breakpoint_count--;
45690 	heap->dbg_breakpoints_active[0] = (duk_breakpoint *) NULL;
45691 
45692 	DUK_HSTRING_DECREF(thr, h);  /* side effects */
45693 	DUK_UNREF(h);  /* w/o refcounting */
45694 
45695 	/* Breakpoint entries above the used area are left as garbage. */
45696 
45697 	return 1;
45698 }
45699 
45700 /*
45701  *  Misc state management
45702  */
45703 
45704 DUK_INTERNAL duk_bool_t duk_debug_is_attached(duk_heap *heap) {
45705 	return (heap->dbg_read_cb != NULL);
45706 }
45707 
45708 DUK_INTERNAL duk_bool_t duk_debug_is_paused(duk_heap *heap) {
45709 	return (DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) != 0);
45710 }
45711 
45712 DUK_INTERNAL void duk_debug_set_paused(duk_heap *heap) {
45713 	if (duk_debug_is_paused(heap)) {
45714 		DUK_D(DUK_DPRINT("trying to set paused state when already paused, ignoring"));
45715 	} else {
45716 		DUK_HEAP_SET_DEBUGGER_PAUSED(heap);
45717 		heap->dbg_state_dirty = 1;
45718 		duk_debug_clear_pause_state(heap);
45719 		DUK_ASSERT(heap->ms_running == 0);  /* debugger can't be triggered within mark-and-sweep */
45720 		heap->ms_running = 1;  /* prevent mark-and-sweep, prevent refzero queueing */
45721 		heap->ms_prevent_count++;
45722 		DUK_ASSERT(heap->ms_prevent_count != 0);  /* Wrap. */
45723 		DUK_ASSERT(heap->heap_thread != NULL);
45724 	}
45725 }
45726 
45727 DUK_INTERNAL void duk_debug_clear_paused(duk_heap *heap) {
45728 	if (duk_debug_is_paused(heap)) {
45729 		DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap);
45730 		heap->dbg_state_dirty = 1;
45731 		duk_debug_clear_pause_state(heap);
45732 		DUK_ASSERT(heap->ms_running == 1);
45733 		DUK_ASSERT(heap->ms_prevent_count > 0);
45734 		heap->ms_prevent_count--;
45735 		heap->ms_running = 0;
45736 		DUK_ASSERT(heap->heap_thread != NULL);
45737 	} else {
45738 		DUK_D(DUK_DPRINT("trying to clear paused state when not paused, ignoring"));
45739 	}
45740 }
45741 
45742 DUK_INTERNAL void duk_debug_clear_pause_state(duk_heap *heap) {
45743 	heap->dbg_pause_flags = 0;
45744 	heap->dbg_pause_act = NULL;
45745 	heap->dbg_pause_startline = 0;
45746 }
45747 
45748 #else  /* DUK_USE_DEBUGGER_SUPPORT */
45749 
45750 /* No debugger support. */
45751 
45752 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
45753 
45754 /* automatic undefs */
45755 #undef DUK__DBG_TPORT_ENTER
45756 #undef DUK__DBG_TPORT_EXIT
45757 #undef DUK__SET_CONN_BROKEN
45758 #line 1 "duk_error_augment.c"
45759 /*
45760  *  Augmenting errors at their creation site and their throw site.
45761  *
45762  *  When errors are created, traceback data is added by built-in code
45763  *  and a user error handler (if defined) can process or replace the
45764  *  error.  Similarly, when errors are thrown, a user error handler
45765  *  (if defined) can process or replace the error.
45766  *
45767  *  Augmentation and other processing at error creation time is nice
45768  *  because an error is only created once, but it may be thrown and
45769  *  rethrown multiple times.  User error handler registered for processing
45770  *  an error at its throw site must be careful to handle rethrowing in
45771  *  a useful manner.
45772  *
45773  *  Error augmentation may throw an internal error (e.g. alloc error).
45774  *
45775  *  ECMAScript allows throwing any values, so all values cannot be
45776  *  augmented.  Currently, the built-in augmentation at error creation
45777  *  only augments error values which are Error instances (= have the
45778  *  built-in Error.prototype in their prototype chain) and are also
45779  *  extensible.  User error handlers have no limitations in this respect.
45780  */
45781 
45782 /* #include duk_internal.h -> already included */
45783 
45784 /*
45785  *  Helper for calling a user error handler.
45786  *
45787  *  'thr' must be the currently active thread; the error handler is called
45788  *  in its context.  The valstack of 'thr' must have the error value on
45789  *  top, and will be replaced by another error value based on the return
45790  *  value of the error handler.
45791  *
45792  *  The helper calls duk_handle_call() recursively in protected mode.
45793  *  Before that call happens, no longjmps should happen; as a consequence,
45794  *  we must assume that the valstack contains enough temporary space for
45795  *  arguments and such.
45796  *
45797  *  While the error handler runs, any errors thrown will not trigger a
45798  *  recursive error handler call (this is implemented using a heap level
45799  *  flag which will "follow" through any coroutines resumed inside the
45800  *  error handler).  If the error handler is not callable or throws an
45801  *  error, the resulting error replaces the original error (for Duktape
45802  *  internal errors, duk_error_throw.c further substitutes this error with
45803  *  a DoubleError which is not ideal).  This would be easy to change and
45804  *  even signal to the caller.
45805  *
45806  *  The user error handler is stored in 'Duktape.errCreate' or
45807  *  'Duktape.errThrow' depending on whether we're augmenting the error at
45808  *  creation or throw time.  There are several alternatives to this approach,
45809  *  see doc/error-objects.rst for discussion.
45810  *
45811  *  Note: since further longjmp()s may occur while calling the error handler
45812  *  (for many reasons, e.g. a labeled 'break' inside the handler), the
45813  *  caller can make no assumptions on the thr->heap->lj state after the
45814  *  call (this affects especially duk_error_throw.c).  This is not an issue
45815  *  as long as the caller writes to the lj state only after the error handler
45816  *  finishes.
45817  */
45818 
45819 #if defined(DUK_USE_ERRTHROW) || defined(DUK_USE_ERRCREATE)
45820 DUK_LOCAL void duk__err_augment_user(duk_hthread *thr, duk_small_uint_t stridx_cb) {
45821 	duk_tval *tv_hnd;
45822 	duk_int_t rc;
45823 
45824 	DUK_ASSERT(thr != NULL);
45825 	DUK_ASSERT(thr->heap != NULL);
45826 	DUK_ASSERT_STRIDX_VALID(stridx_cb);
45827 
45828 	if (thr->heap->augmenting_error) {
45829 		DUK_D(DUK_DPRINT("recursive call to error augmentation, ignore"));
45830 		return;
45831 	}
45832 
45833 	/*
45834 	 *  Check whether or not we have an error handler.
45835 	 *
45836 	 *  We must be careful of not triggering an error when looking up the
45837 	 *  property.  For instance, if the property is a getter, we don't want
45838 	 *  to call it, only plain values are allowed.  The value, if it exists,
45839 	 *  is not checked.  If the value is not a function, a TypeError happens
45840 	 *  when it is called and that error replaces the original one.
45841 	 */
45842 
45843 	DUK_ASSERT_VALSTACK_SPACE(thr, 4);  /* 3 entries actually needed below */
45844 
45845 	/* [ ... errval ] */
45846 
45847 	if (thr->builtins[DUK_BIDX_DUKTAPE] == NULL) {
45848 		/* When creating built-ins, some of the built-ins may not be set
45849 		 * and we want to tolerate that when throwing errors.
45850 		 */
45851 		DUK_DD(DUK_DDPRINT("error occurred when DUK_BIDX_DUKTAPE is NULL, ignoring"));
45852 		return;
45853 	}
45854 	tv_hnd = duk_hobject_find_existing_entry_tval_ptr(thr->heap,
45855 	                                                  thr->builtins[DUK_BIDX_DUKTAPE],
45856 	                                                  DUK_HTHREAD_GET_STRING(thr, stridx_cb));
45857 	if (tv_hnd == NULL) {
45858 		DUK_DD(DUK_DDPRINT("error handler does not exist or is not a plain value: %!T",
45859 		                   (duk_tval *) tv_hnd));
45860 		return;
45861 	}
45862 	DUK_DDD(DUK_DDDPRINT("error handler dump (callability not checked): %!T",
45863 	                     (duk_tval *) tv_hnd));
45864 	duk_push_tval(thr, tv_hnd);
45865 
45866 	/* [ ... errval errhandler ] */
45867 
45868 	duk_insert(thr, -2);  /* -> [ ... errhandler errval ] */
45869 	duk_push_undefined(thr);
45870 	duk_insert(thr, -2);  /* -> [ ... errhandler undefined(= this) errval ] */
45871 
45872 	/* [ ... errhandler undefined errval ] */
45873 
45874 	/*
45875 	 *  heap->augmenting_error prevents recursive re-entry and also causes
45876 	 *  call handling to use a larger (but not unbounded) call stack limit
45877 	 *  for the duration of error augmentation.
45878 	 *
45879 	 *  We ignore errors now: a success return and an error value both
45880 	 *  replace the original error value.  (This would be easy to change.)
45881 	 */
45882 
45883 	DUK_ASSERT(thr->heap->augmenting_error == 0);
45884 	thr->heap->augmenting_error = 1;
45885 
45886 	rc = duk_pcall_method(thr, 1);
45887 	DUK_UNREF(rc);  /* no need to check now: both success and error are OK */
45888 
45889 	DUK_ASSERT(thr->heap->augmenting_error == 1);
45890 	thr->heap->augmenting_error = 0;
45891 
45892 	/* [ ... errval ] */
45893 }
45894 #endif  /* DUK_USE_ERRTHROW || DUK_USE_ERRCREATE */
45895 
45896 /*
45897  *  Add ._Tracedata to an error on the stack top.
45898  */
45899 
45900 #if defined(DUK_USE_TRACEBACKS)
45901 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) {
45902 	duk_activation *act;
45903 	duk_int_t depth;
45904 	duk_int_t arr_size;
45905 	duk_tval *tv;
45906 	duk_hstring *s;
45907 	duk_uint32_t u32;
45908 	duk_double_t d;
45909 
45910 	DUK_ASSERT(thr != NULL);
45911 	DUK_ASSERT(thr_callstack != NULL);
45912 
45913 	/* [ ... error ] */
45914 
45915 	/*
45916 	 *  The traceback format is pretty arcane in an attempt to keep it compact
45917 	 *  and cheap to create.  It may change arbitrarily from version to version.
45918 	 *  It should be decoded/accessed through version specific accessors only.
45919 	 *
45920 	 *  See doc/error-objects.rst.
45921 	 */
45922 
45923 	DUK_DDD(DUK_DDDPRINT("adding traceback to object: %!T",
45924 	                     (duk_tval *) duk_get_tval(thr, -1)));
45925 
45926 	/* Preallocate array to correct size, so that we can just write out
45927 	 * the _Tracedata values into the array part.
45928 	 */
45929 	act = thr->callstack_curr;
45930 	depth = DUK_USE_TRACEBACK_DEPTH;
45931 	DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
45932 	if (depth > (duk_int_t) thr_callstack->callstack_top) {
45933 		depth = (duk_int_t) thr_callstack->callstack_top;
45934 	}
45935 	if (depth > 0) {
45936 		if (flags & DUK_AUGMENT_FLAG_SKIP_ONE) {
45937 			DUK_ASSERT(act != NULL);
45938 			act = act->parent;
45939 			depth--;
45940 		}
45941 	}
45942 	arr_size = depth * 2;
45943 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
45944 		arr_size += 2;
45945 	}
45946 	if (c_filename) {
45947 		/* We need the C filename to be interned before getting the
45948 		 * array part pointer to avoid any GC interference while the
45949 		 * array part is populated.
45950 		 */
45951 		duk_push_string(thr, c_filename);
45952 		arr_size += 2;
45953 	}
45954 
45955 	/* XXX: uninitialized would be OK */
45956 	DUK_D(DUK_DPRINT("preallocated _Tracedata to %ld items", (long) arr_size));
45957 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) arr_size);
45958 	DUK_ASSERT(arr_size == 0 || tv != NULL);
45959 
45960 	/* Compiler SyntaxErrors (and other errors) come first, and are
45961 	 * blamed by default (not flagged "noblame").
45962 	 */
45963 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
45964 		s = thr->compile_ctx->h_filename;
45965 		DUK_TVAL_SET_STRING(tv, s);
45966 		DUK_HSTRING_INCREF(thr, s);
45967 		tv++;
45968 
45969 		u32 = (duk_uint32_t) thr->compile_ctx->curr_token.start_line;  /* (flags<<32) + (line), flags = 0 */
45970 		DUK_TVAL_SET_U32(tv, u32);
45971 		tv++;
45972 	}
45973 
45974 	/* Filename/line from C macros (__FILE__, __LINE__) are added as an
45975 	 * entry with a special format: (string, number).  The number contains
45976 	 * the line and flags.
45977 	 */
45978 
45979 	/* [ ... error c_filename? arr ] */
45980 
45981 	if (c_filename) {
45982 		DUK_ASSERT(DUK_TVAL_IS_STRING(thr->valstack_top - 2));
45983 		s = DUK_TVAL_GET_STRING(thr->valstack_top - 2);  /* interned c_filename */
45984 		DUK_ASSERT(s != NULL);
45985 		DUK_TVAL_SET_STRING(tv, s);
45986 		DUK_HSTRING_INCREF(thr, s);
45987 		tv++;
45988 
45989 		d = ((flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) ? ((duk_double_t) DUK_TB_FLAG_NOBLAME_FILELINE) * DUK_DOUBLE_2TO32 : 0.0) +
45990 		    (duk_double_t) c_line;
45991 		DUK_TVAL_SET_DOUBLE(tv, d);
45992 		tv++;
45993 	}
45994 
45995 	/* Traceback depth doesn't take into account the filename/line
45996 	 * special handling above (intentional).
45997 	 */
45998 	for (; depth-- > 0; act = act->parent) {
45999 		duk_uint32_t pc;
46000 		duk_tval *tv_src;
46001 
46002 		/* [... arr] */
46003 
46004 		DUK_ASSERT(act != NULL);  /* depth check above, assumes book-keeping is correct */
46005 		DUK_ASSERT_DISABLE(act->pc >= 0);  /* unsigned */
46006 
46007 		/* Add function object. */
46008 		tv_src = &act->tv_func;  /* object (function) or lightfunc */
46009 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv_src) || DUK_TVAL_IS_LIGHTFUNC(tv_src));
46010 		DUK_TVAL_SET_TVAL(tv, tv_src);
46011 		DUK_TVAL_INCREF(thr, tv);
46012 		tv++;
46013 
46014 		/* Add a number containing: pc, activation flags.
46015 		 *
46016 		 * PC points to next instruction, find offending PC.  Note that
46017 		 * PC == 0 for native code.
46018 		 */
46019 		pc = (duk_uint32_t) duk_hthread_get_act_prev_pc(thr_callstack, act);
46020 		DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46021 		DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46022 		d = ((duk_double_t) act->flags) * DUK_DOUBLE_2TO32 + (duk_double_t) pc;
46023 		DUK_TVAL_SET_DOUBLE(tv, d);
46024 		tv++;
46025 	}
46026 
46027 #if defined(DUK_USE_ASSERTIONS)
46028 	{
46029 		duk_harray *a;
46030 		a = (duk_harray *) duk_known_hobject(thr, -1);
46031 		DUK_ASSERT(a != NULL);
46032 		DUK_ASSERT((duk_uint32_t) (tv - DUK_HOBJECT_A_GET_BASE(thr->heap, (duk_hobject *) a)) == a->length);
46033 		DUK_ASSERT(a->length == (duk_uint32_t) arr_size);
46034 	}
46035 #endif
46036 
46037 	/* [ ... error c_filename? arr ] */
46038 
46039 	if (c_filename) {
46040 		duk_remove_m2(thr);
46041 	}
46042 
46043 	/* [ ... error arr ] */
46044 
46045 	duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INT_TRACEDATA);  /* -> [ ... error ] */
46046 }
46047 #endif  /* DUK_USE_TRACEBACKS */
46048 
46049 /*
46050  *  Add .fileName and .lineNumber to an error on the stack top.
46051  */
46052 
46053 #if defined(DUK_USE_AUGMENT_ERROR_CREATE) && !defined(DUK_USE_TRACEBACKS)
46054 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) {
46055 #if defined(DUK_USE_ASSERTIONS)
46056 	duk_int_t entry_top;
46057 #endif
46058 
46059 #if defined(DUK_USE_ASSERTIONS)
46060 	entry_top = duk_get_top(thr);
46061 #endif
46062 
46063 	/*
46064 	 *  If tracebacks are disabled, 'fileName' and 'lineNumber' are added
46065 	 *  as plain own properties.  Since Error.prototype has accessors of
46066 	 *  the same name, we need to define own properties directly (cannot
46067 	 *  just use e.g. duk_put_prop_stridx).  Existing properties are not
46068 	 *  overwritten in case they already exist.
46069 	 */
46070 
46071 	if (thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL) {
46072 		/* Compiler SyntaxError (or other error) gets the primary blame.
46073 		 * Currently no flag to prevent blaming.
46074 		 */
46075 		duk_push_uint(thr, (duk_uint_t) thr->compile_ctx->curr_token.start_line);
46076 		duk_push_hstring(thr, thr->compile_ctx->h_filename);
46077 	} else if (c_filename && (flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE) == 0) {
46078 		/* C call site gets blamed next, unless flagged not to do so.
46079 		 * XXX: file/line is disabled in minimal builds, so disable this
46080 		 * too when appropriate.
46081 		 */
46082 		duk_push_int(thr, c_line);
46083 		duk_push_string(thr, c_filename);
46084 	} else {
46085 		/* Finally, blame the innermost callstack entry which has a
46086 		 * .fileName property.
46087 		 */
46088 		duk_small_uint_t depth;
46089 		duk_uint32_t ecma_line;
46090 		duk_activation *act;
46091 
46092 		DUK_ASSERT(thr_callstack->callstack_top <= DUK_INT_MAX);  /* callstack limits */
46093 		depth = DUK_USE_TRACEBACK_DEPTH;
46094 		if (depth > thr_callstack->callstack_top) {
46095 			depth = thr_callstack->callstack_top;
46096 		}
46097 		for (act = thr_callstack->callstack_curr; depth-- > 0; act = act->parent) {
46098 			duk_hobject *func;
46099 			duk_uint32_t pc;
46100 
46101 			DUK_ASSERT(act != NULL);
46102 			func = DUK_ACT_GET_FUNC(act);
46103 			if (func == NULL) {
46104 				/* Lightfunc, not blamed now. */
46105 				continue;
46106 			}
46107 
46108 			/* PC points to next instruction, find offending PC,
46109 			 * PC == 0 for native code.
46110 			 */
46111 			pc = duk_hthread_get_act_prev_pc(thr, act);  /* thr argument only used for thr->heap, so specific thread doesn't matter */
46112 			DUK_UNREF(pc);
46113 			DUK_ASSERT_DISABLE(pc >= 0);  /* unsigned */
46114 			DUK_ASSERT((duk_double_t) pc < DUK_DOUBLE_2TO32);  /* assume PC is at most 32 bits and non-negative */
46115 
46116 			duk_push_hobject(thr, func);
46117 
46118 			/* [ ... error func ] */
46119 
46120 			duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_FILE_NAME);
46121 			if (!duk_is_string_notsymbol(thr, -1)) {
46122 				duk_pop_2(thr);
46123 				continue;
46124 			}
46125 
46126 			/* [ ... error func fileName ] */
46127 
46128 			ecma_line = 0;
46129 #if defined(DUK_USE_PC2LINE)
46130 			if (DUK_HOBJECT_IS_COMPFUNC(func)) {
46131 				ecma_line = duk_hobject_pc2line_query(thr, -2, (duk_uint_fast32_t) pc);
46132 			} else {
46133 				/* Native function, no relevant lineNumber. */
46134 			}
46135 #endif  /* DUK_USE_PC2LINE */
46136 			duk_push_u32(thr, ecma_line);
46137 
46138 			/* [ ... error func fileName lineNumber ] */
46139 
46140 			duk_replace(thr, -3);
46141 
46142 			/* [ ... error lineNumber fileName ] */
46143 			goto define_props;
46144 		}
46145 
46146 		/* No activation matches, use undefined for both .fileName and
46147 		 * .lineNumber (matches what we do with a _Tracedata based
46148 		 * no-match lookup.
46149 		 */
46150 		duk_push_undefined(thr);
46151 		duk_push_undefined(thr);
46152 	}
46153 
46154  define_props:
46155 	/* [ ... error lineNumber fileName ] */
46156 #if defined(DUK_USE_ASSERTIONS)
46157 	DUK_ASSERT(duk_get_top(thr) == entry_top + 2);
46158 #endif
46159 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46160 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LINE_NUMBER, DUK_PROPDESC_FLAGS_C | DUK_PROPDESC_FLAG_NO_OVERWRITE);
46161 }
46162 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE && !DUK_USE_TRACEBACKS */
46163 
46164 /*
46165  *  Add line number to a compiler error.
46166  */
46167 
46168 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46169 DUK_LOCAL void duk__add_compiler_error_line(duk_hthread *thr) {
46170 
46171 	/* Append a "(line NNN)" to the "message" property of any error
46172 	 * thrown during compilation.  Usually compilation errors are
46173 	 * SyntaxErrors but they can also be out-of-memory errors and
46174 	 * the like.
46175 	 */
46176 
46177 	/* [ ... error ] */
46178 
46179 	DUK_ASSERT(duk_is_object(thr, -1));
46180 
46181 	if (!(thr->compile_ctx != NULL && thr->compile_ctx->h_filename != NULL)) {
46182 		return;
46183 	}
46184 
46185 	DUK_DDD(DUK_DDDPRINT("compile error, before adding line info: %!T",
46186 	                     (duk_tval *) duk_get_tval(thr, -1)));
46187 
46188 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_MESSAGE)) {
46189 		duk_push_sprintf(thr, " (line %ld)", (long) thr->compile_ctx->curr_token.start_line);
46190 		duk_concat(thr, 2);
46191 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_MESSAGE);
46192 	} else {
46193 		duk_pop(thr);
46194 	}
46195 
46196 	DUK_DDD(DUK_DDDPRINT("compile error, after adding line info: %!T",
46197 	                     (duk_tval *) duk_get_tval(thr, -1)));
46198 }
46199 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46200 
46201 /*
46202  *  Augment an error being created using Duktape specific properties
46203  *  like _Tracedata or .fileName/.lineNumber.
46204  */
46205 
46206 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46207 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) {
46208 #if defined(DUK_USE_ASSERTIONS)
46209 	duk_int_t entry_top;
46210 #endif
46211 
46212 #if defined(DUK_USE_ASSERTIONS)
46213 	entry_top = duk_get_top(thr);
46214 #endif
46215 	DUK_ASSERT(obj != NULL);
46216 
46217 	DUK_UNREF(obj);  /* unreferenced w/o tracebacks */
46218 
46219 	duk__add_compiler_error_line(thr);
46220 
46221 #if defined(DUK_USE_TRACEBACKS)
46222 	/* If tracebacks are enabled, the '_Tracedata' property is the only
46223 	 * thing we need: 'fileName' and 'lineNumber' are virtual properties
46224 	 * which use '_Tracedata'.
46225 	 */
46226 	if (duk_hobject_hasprop_raw(thr, obj, DUK_HTHREAD_STRING_INT_TRACEDATA(thr))) {
46227 		DUK_DDD(DUK_DDDPRINT("error value already has a '_Tracedata' property, not modifying it"));
46228 	} else {
46229 		duk__add_traceback(thr, thr_callstack, c_filename, c_line, flags);
46230 	}
46231 #else
46232 	/* Without tracebacks the concrete .fileName and .lineNumber need
46233 	 * to be added directly.
46234 	 */
46235 	duk__add_fileline(thr, thr_callstack, c_filename, c_line, flags);
46236 #endif
46237 
46238 #if defined(DUK_USE_ASSERTIONS)
46239 	DUK_ASSERT(duk_get_top(thr) == entry_top);
46240 #endif
46241 }
46242 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46243 
46244 /*
46245  *  Augment an error at creation time with _Tracedata/fileName/lineNumber
46246  *  and allow a user error handler (if defined) to process/replace the error.
46247  *  The error to be augmented is at the stack top.
46248  *
46249  *  thr: thread containing the error value
46250  *  thr_callstack: thread which should be used for generating callstack etc.
46251  *  c_filename: C __FILE__ related to the error
46252  *  c_line: C __LINE__ related to the error
46253  *  flags & DUK_AUGMENT_FLAG_NOBLAME_FILELINE:
46254  *      if true, don't fileName/line as error source, otherwise use traceback
46255  *      (needed because user code filename/line are reported but internal ones
46256  *      are not)
46257  */
46258 
46259 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
46260 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) {
46261 	duk_hobject *obj;
46262 
46263 	DUK_ASSERT(thr != NULL);
46264 	DUK_ASSERT(thr_callstack != NULL);
46265 
46266 	/* [ ... error ] */
46267 
46268 	/*
46269 	 *  Criteria for augmenting:
46270 	 *
46271 	 *   - augmentation enabled in build (naturally)
46272 	 *   - error value internal prototype chain contains the built-in
46273 	 *     Error prototype object (i.e. 'val instanceof Error')
46274 	 *
46275 	 *  Additional criteria for built-in augmenting:
46276 	 *
46277 	 *   - error value is an extensible object
46278 	 */
46279 
46280 	obj = duk_get_hobject(thr, -1);
46281 	if (!obj) {
46282 		DUK_DDD(DUK_DDDPRINT("value is not an object, skip both built-in and user augment"));
46283 		return;
46284 	}
46285 	if (!duk_hobject_prototype_chain_contains(thr, obj, thr->builtins[DUK_BIDX_ERROR_PROTOTYPE], 1 /*ignore_loop*/)) {
46286 		/* If the value has a prototype loop, it's critical not to
46287 		 * throw here.  Instead, assume the value is not to be
46288 		 * augmented.
46289 		 */
46290 		DUK_DDD(DUK_DDDPRINT("value is not an error instance, skip both built-in and user augment"));
46291 		return;
46292 	}
46293 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
46294 		DUK_DDD(DUK_DDDPRINT("error meets criteria, built-in augment"));
46295 		duk__err_augment_builtin_create(thr, thr_callstack, c_filename, c_line, obj, flags);
46296 	} else {
46297 		DUK_DDD(DUK_DDDPRINT("error does not meet criteria, no built-in augment"));
46298 	}
46299 
46300 	/* [ ... error ] */
46301 
46302 #if defined(DUK_USE_ERRCREATE)
46303 	duk__err_augment_user(thr, DUK_STRIDX_ERR_CREATE);
46304 #endif
46305 }
46306 #endif  /* DUK_USE_AUGMENT_ERROR_CREATE */
46307 
46308 /*
46309  *  Augment an error at throw time; allow a user error handler (if defined)
46310  *  to process/replace the error.  The error to be augmented is at the
46311  *  stack top.
46312  */
46313 
46314 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46315 DUK_INTERNAL void duk_err_augment_error_throw(duk_hthread *thr) {
46316 #if defined(DUK_USE_ERRTHROW)
46317 	duk__err_augment_user(thr, DUK_STRIDX_ERR_THROW);
46318 #endif  /* DUK_USE_ERRTHROW */
46319 }
46320 #endif  /* DUK_USE_AUGMENT_ERROR_THROW */
46321 #line 1 "duk_error_longjmp.c"
46322 /*
46323  *  Do a longjmp call, calling the fatal error handler if no
46324  *  catchpoint exists.
46325  */
46326 
46327 /* #include duk_internal.h -> already included */
46328 
46329 #if defined(DUK_USE_PREFER_SIZE)
46330 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_minimal(duk_hthread *thr));
46331 DUK_LOCAL void duk__uncaught_minimal(duk_hthread *thr) {
46332 	(void) duk_fatal(thr, "uncaught error");
46333 	DUK_WO_NORETURN(return;);
46334 }
46335 #endif
46336 
46337 #if 0
46338 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_readable(duk_hthread *thr));
46339 DUK_LOCAL void duk__uncaught_readable(duk_hthread *thr) {
46340 	const char *summary;
46341 	char buf[DUK_USE_FATAL_MAXLEN];
46342 
46343 	summary = duk_push_string_tval_readable(thr, &thr->heap->lj.value1);
46344 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46345 	buf[sizeof(buf) - 1] = (char) 0;
46346 	(void) duk_fatal(thr, (const char *) buf);
46347 	DUK_WO_NORETURN(return;);
46348 }
46349 #endif
46350 
46351 #if !defined(DUK_USE_PREFER_SIZE)
46352 DUK_NORETURN(DUK_LOCAL_DECL void duk__uncaught_error_aware(duk_hthread *thr));
46353 DUK_LOCAL void duk__uncaught_error_aware(duk_hthread *thr) {
46354 	const char *summary;
46355 	char buf[DUK_USE_FATAL_MAXLEN];
46356 
46357 	summary = duk_push_string_tval_readable_error(thr, &thr->heap->lj.value1);
46358 	DUK_ASSERT(summary != NULL);
46359 	DUK_SNPRINTF(buf, sizeof(buf), "uncaught: %s", summary);
46360 	buf[sizeof(buf) - 1] = (char) 0;
46361 	(void) duk_fatal(thr, (const char *) buf);
46362 	DUK_WO_NORETURN(return;);
46363 }
46364 #endif
46365 
46366 DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
46367 	DUK_ASSERT(thr != NULL);
46368 	DUK_ASSERT(thr->heap != NULL);
46369 
46370 	DUK_DD(DUK_DDPRINT("longjmp error: type=%d iserror=%d value1=%!T value2=%!T",
46371 	                   (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46372 	                   &thr->heap->lj.value1, &thr->heap->lj.value2));
46373 
46374 	/* Prevent finalizer execution during error handling.  All error
46375 	 * handling sites will process pending finalizers once error handling
46376 	 * is complete and we're ready for the side effects.  Does not prevent
46377 	 * refzero freeing or mark-and-sweep during error handling.
46378 	 *
46379 	 * NOTE: when we come here some calling code may have used DECREF
46380 	 * NORZ macros without an explicit DUK_REFZERO_CHECK_xxx() call.
46381 	 * We don't want to do it here because it would just check for
46382 	 * pending finalizers and we prevent that explicitly.  Instead,
46383 	 * the error catcher will run the finalizers once error handling
46384 	 * is complete.
46385 	 */
46386 
46387 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46388 
46389 	thr->heap->pf_prevent_count++;
46390 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
46391 
46392 #if defined(DUK_USE_ASSERTIONS)
46393 	/* XXX: set this immediately when longjmp state is set */
46394 	DUK_ASSERT(thr->heap->error_not_allowed == 0);  /* Detect error within critical section. */
46395 	thr->heap->error_not_allowed = 1;
46396 #endif
46397 
46398 	DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
46399 
46400 	/* If we don't have a jmpbuf_ptr, there is little we can do except
46401 	 * cause a fatal error.  The caller's expectation is that we never
46402 	 * return.
46403 	 */
46404 	if (!thr->heap->lj.jmpbuf_ptr) {
46405 		DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
46406 		                 (int) thr->heap->lj.type, (int) thr->heap->lj.iserror,
46407 		                 &thr->heap->lj.value1, &thr->heap->lj.value2));
46408 
46409 #if defined(DUK_USE_PREFER_SIZE)
46410 		duk__uncaught_minimal(thr);
46411 #else
46412 		duk__uncaught_error_aware(thr);
46413 #endif
46414 		DUK_UNREACHABLE();
46415 	}
46416 
46417 #if defined(DUK_USE_CPP_EXCEPTIONS)
46418 	throw duk_internal_exception();  /* dummy */
46419 #else
46420 	DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
46421 #endif
46422 
46423 	DUK_UNREACHABLE();
46424 }
46425 #line 1 "duk_error_misc.c"
46426 /*
46427  *  Error helpers
46428  */
46429 
46430 /* #include duk_internal.h -> already included */
46431 
46432 /*
46433  *  Helper to walk the thread chain and see if there is an active error
46434  *  catcher.  Protected calls or finally blocks aren't considered catching.
46435  */
46436 
46437 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46438 DUK_LOCAL duk_bool_t duk__have_active_catcher(duk_hthread *thr) {
46439 	/* As noted above, a protected API call won't be counted as a
46440 	 * catcher.  This is usually convenient, e.g. in the case of a top-
46441 	 * level duk_pcall(), but may not always be desirable.  Perhaps add
46442 	 * an argument to treat them as catchers?
46443 	 */
46444 
46445 	duk_activation *act;
46446 	duk_catcher *cat;
46447 
46448 	DUK_ASSERT(thr != NULL);
46449 
46450 	for (; thr != NULL; thr = thr->resumer) {
46451 		for (act = thr->callstack_curr; act != NULL; act = act->parent) {
46452 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
46453 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
46454 					return 1;  /* all we need to know */
46455 				}
46456 			}
46457 		}
46458 	}
46459 	return 0;
46460 }
46461 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46462 
46463 /*
46464  *  Get prototype object for an integer error code.
46465  */
46466 
46467 DUK_INTERNAL duk_hobject *duk_error_prototype_from_code(duk_hthread *thr, duk_errcode_t code) {
46468 	switch (code) {
46469 	case DUK_ERR_EVAL_ERROR:
46470 		return thr->builtins[DUK_BIDX_EVAL_ERROR_PROTOTYPE];
46471 	case DUK_ERR_RANGE_ERROR:
46472 		return thr->builtins[DUK_BIDX_RANGE_ERROR_PROTOTYPE];
46473 	case DUK_ERR_REFERENCE_ERROR:
46474 		return thr->builtins[DUK_BIDX_REFERENCE_ERROR_PROTOTYPE];
46475 	case DUK_ERR_SYNTAX_ERROR:
46476 		return thr->builtins[DUK_BIDX_SYNTAX_ERROR_PROTOTYPE];
46477 	case DUK_ERR_TYPE_ERROR:
46478 		return thr->builtins[DUK_BIDX_TYPE_ERROR_PROTOTYPE];
46479 	case DUK_ERR_URI_ERROR:
46480 		return thr->builtins[DUK_BIDX_URI_ERROR_PROTOTYPE];
46481 	case DUK_ERR_ERROR:
46482 	default:
46483 		return thr->builtins[DUK_BIDX_ERROR_PROTOTYPE];
46484 	}
46485 }
46486 
46487 /*
46488  *  Helper for debugger throw notify and pause-on-uncaught integration.
46489  */
46490 
46491 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46492 DUK_INTERNAL void duk_err_check_debugger_integration(duk_hthread *thr) {
46493 	duk_bool_t uncaught;
46494 	duk_tval *tv_obj;
46495 
46496 	/* If something is thrown with the debugger attached and nobody will
46497 	 * catch it, execution is paused before the longjmp, turning over
46498 	 * control to the debug client.  This allows local state to be examined
46499 	 * before the stack is unwound.  Errors are not intercepted when debug
46500 	 * message loop is active (e.g. for Eval).
46501 	 */
46502 
46503 	DUK_ASSERT(thr != NULL);
46504 	DUK_ASSERT(thr->heap != NULL);
46505 
46506 	/* XXX: Allow customizing the pause and notify behavior at runtime
46507 	 * using debugger runtime flags.  For now the behavior is fixed using
46508 	 * config options.
46509 	 */
46510 
46511 	if (!duk_debug_is_attached(thr->heap) ||
46512 	    thr->heap->dbg_processing ||
46513 	    thr->heap->lj.type != DUK_LJ_TYPE_THROW ||
46514 	    thr->heap->creating_error) {
46515 		DUK_D(DUK_DPRINT("skip debugger error integration; not attached, debugger processing, not THROW, or error thrown while creating error"));
46516 		return;
46517 	}
46518 
46519 	/* Don't intercept a DoubleError, we may have caused the initial double
46520 	 * fault and attempting to intercept it will cause us to be called
46521 	 * recursively and exhaust the C stack.  (This should no longer happen
46522 	 * for the initial throw because DoubleError path doesn't do a debugger
46523 	 * integration check, but it might happen for rethrows.)
46524 	 */
46525 	tv_obj = &thr->heap->lj.value1;
46526 	if (DUK_TVAL_IS_OBJECT(tv_obj) && DUK_TVAL_GET_OBJECT(tv_obj) == thr->builtins[DUK_BIDX_DOUBLE_ERROR]) {
46527 		DUK_D(DUK_DPRINT("built-in DoubleError instance (re)thrown, not intercepting"));
46528 		return;
46529 	}
46530 
46531 	uncaught = !duk__have_active_catcher(thr);
46532 
46533 	/* Debugger code expects the value at stack top.  This also serves
46534 	 * as a backup: we need to store/restore the longjmp state because
46535 	 * when the debugger is paused Eval commands may be executed and
46536 	 * they can arbitrarily clobber the longjmp state.
46537 	 */
46538 	duk_push_tval(thr, tv_obj);
46539 
46540 	/* Store and reset longjmp state. */
46541 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46542 	DUK_TVAL_DECREF_NORZ(thr, tv_obj);
46543 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));  /* Always for THROW type. */
46544 	DUK_TVAL_SET_UNDEFINED(tv_obj);
46545 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
46546 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46547 
46548 #if defined(DUK_USE_DEBUGGER_THROW_NOTIFY)
46549 	/* Report it to the debug client */
46550 	DUK_D(DUK_DPRINT("throw with debugger attached, report to client"));
46551 	duk_debug_send_throw(thr, uncaught);
46552 #endif
46553 
46554 	if (uncaught) {
46555 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_UNCAUGHT_ERROR) {
46556 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by uncaught error"));
46557 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46558 		}
46559 	} else {
46560 		if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_CAUGHT_ERROR) {
46561 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by caught error"));
46562 			duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
46563 		}
46564 	}
46565 
46566 	/* Restore longjmp state. */
46567 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46568 	thr->heap->lj.type = DUK_LJ_TYPE_THROW;
46569 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -1);
46570 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value1));
46571 	DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(&thr->heap->lj.value2));
46572 	DUK_TVAL_SET_TVAL(&thr->heap->lj.value1, tv_obj);
46573 	DUK_TVAL_INCREF(thr, tv_obj);
46574 	DUK_ASSERT_LJSTATE_SET(thr->heap);
46575 
46576 	duk_pop(thr);
46577 }
46578 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
46579 
46580 /*
46581  *  Helpers for setting up heap longjmp state.
46582  */
46583 
46584 DUK_INTERNAL void duk_err_setup_ljstate1(duk_hthread *thr, duk_small_uint_t lj_type, duk_tval *tv_val) {
46585 	duk_heap *heap;
46586 
46587 	DUK_ASSERT(thr != NULL);
46588 	heap = thr->heap;
46589 	DUK_ASSERT(heap != NULL);
46590 	DUK_ASSERT(tv_val != NULL);
46591 
46592 	DUK_ASSERT_LJSTATE_UNSET(heap);
46593 
46594 	heap->lj.type = lj_type;
46595 	DUK_TVAL_SET_TVAL(&heap->lj.value1, tv_val);
46596 	DUK_TVAL_INCREF(thr, tv_val);
46597 
46598 	DUK_ASSERT_LJSTATE_SET(heap);
46599 }
46600 #line 1 "duk_error_throw.c"
46601 /*
46602  *  Create and throw an ECMAScript error object based on a code and a message.
46603  *
46604  *  Used when we throw errors internally.  ECMAScript generated error objects
46605  *  are created by ECMAScript code, and the throwing is handled by the bytecode
46606  *  executor.
46607  */
46608 
46609 /* #include duk_internal.h -> already included */
46610 
46611 /*
46612  *  Create and throw an error (originating from Duktape internally)
46613  *
46614  *  Push an error object on top of the stack, possibly throw augmenting
46615  *  the error, and finally longjmp.
46616  *
46617  *  If an error occurs while we're dealing with the current error, we might
46618  *  enter an infinite recursion loop.  This is prevented by detecting a
46619  *  "double fault" through the heap->creating_error flag; the recursion
46620  *  then stops at the second level.
46621  */
46622 
46623 #if defined(DUK_USE_VERBOSE_ERRORS)
46624 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) {
46625 #else
46626 DUK_INTERNAL void duk_err_create_and_throw(duk_hthread *thr, duk_errcode_t code) {
46627 #endif
46628 #if defined(DUK_USE_VERBOSE_ERRORS)
46629 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld, msg=%s, filename=%s, line=%ld",
46630 	                   (long) code, (const char *) msg,
46631 	                   (const char *) filename, (long) line));
46632 #else
46633 	DUK_DD(DUK_DDPRINT("duk_err_create_and_throw(): code=%ld", (long) code));
46634 #endif
46635 
46636 	DUK_ASSERT(thr != NULL);
46637 
46638 	/* Even though nested call is possible because we throw an error when
46639 	 * trying to create an error, the potential errors must happen before
46640 	 * the longjmp state is configured.
46641 	 */
46642 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
46643 
46644 	/* Sync so that augmentation sees up-to-date activations, NULL
46645 	 * thr->ptr_curr_pc so that it's not used if side effects occur
46646 	 * in augmentation or longjmp handling.
46647 	 */
46648 	duk_hthread_sync_and_null_currpc(thr);
46649 
46650 	/*
46651 	 *  Create and push an error object onto the top of stack.
46652 	 *  The error is potentially augmented before throwing.
46653 	 *
46654 	 *  If a "double error" occurs, use a fixed error instance
46655 	 *  to avoid further trouble.
46656 	 */
46657 
46658 	if (thr->heap->creating_error) {
46659 		duk_tval tv_val;
46660 		duk_hobject *h_err;
46661 
46662 		thr->heap->creating_error = 0;
46663 
46664 		h_err = thr->builtins[DUK_BIDX_DOUBLE_ERROR];
46665 		if (h_err != NULL) {
46666 			DUK_D(DUK_DPRINT("double fault detected -> use built-in fixed 'double error' instance"));
46667 			DUK_TVAL_SET_OBJECT(&tv_val, h_err);
46668 		} else {
46669 			DUK_D(DUK_DPRINT("double fault detected; there is no built-in fixed 'double error' instance "
46670 			                 "-> use the error code as a number"));
46671 			DUK_TVAL_SET_I32(&tv_val, (duk_int32_t) code);
46672 		}
46673 
46674 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, &tv_val);
46675 
46676 		/* No augmentation to avoid any allocations or side effects. */
46677 	} else {
46678 		/* Prevent infinite recursion.  Extra call stack and C
46679 		 * recursion headroom (see GH-191) is added for augmentation.
46680 		 * That is now signalled by heap->augmenting error and taken
46681 		 * into account in call handling without an explicit limit bump.
46682 		 */
46683 		thr->heap->creating_error = 1;
46684 
46685 		duk_require_stack(thr, 1);
46686 
46687 		/* XXX: usually unnecessary '%s' formatting here, but cannot
46688 		 * use 'msg' as a format string directly.
46689 		 */
46690 #if defined(DUK_USE_VERBOSE_ERRORS)
46691 		duk_push_error_object_raw(thr,
46692 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46693 		                          filename,
46694 		                          line,
46695 		                          "%s",
46696 		                          (const char *) msg);
46697 #else
46698 		duk_push_error_object_raw(thr,
46699 		                          code | DUK_ERRCODE_FLAG_NOBLAME_FILELINE,
46700 		                          NULL,
46701 		                          0,
46702 		                          NULL);
46703 #endif
46704 
46705 		/* Note that an alloc error may happen during error augmentation.
46706 		 * This may happen both when the original error is an alloc error
46707 		 * and when it's something else.  Because any error in augmentation
46708 		 * must be handled correctly anyway, there's no special check for
46709 		 * avoiding it for alloc errors (this differs from Duktape 1.x).
46710 		 */
46711 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
46712 		DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT (before throw augment)",
46713 		                     (duk_tval *) duk_get_tval(thr, -1)));
46714 		duk_err_augment_error_throw(thr);
46715 #endif
46716 
46717 		duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
46718 		thr->heap->creating_error = 0;
46719 
46720 		/* Error is now created and we assume no errors can occur any
46721 		 * more.  Check for debugger Throw integration only when the
46722 		 * error is complete.  If we enter debugger message loop,
46723 		 * creating_error must be 0 so that errors can be thrown in
46724 		 * the paused state, e.g. in Eval commands.
46725 		 */
46726 #if defined(DUK_USE_DEBUGGER_SUPPORT)
46727 		duk_err_check_debugger_integration(thr);
46728 #endif
46729 	}
46730 
46731 	/*
46732 	 *  Finally, longjmp
46733 	 */
46734 
46735 	DUK_DDD(DUK_DDDPRINT("THROW ERROR (INTERNAL): %!iT, %!iT (after throw augment)",
46736 	                     (duk_tval *) &thr->heap->lj.value1, (duk_tval *) &thr->heap->lj.value2));
46737 
46738 	duk_err_longjmp(thr);
46739 	DUK_UNREACHABLE();
46740 }
46741 
46742 /*
46743  *  Helper for C function call negative return values.
46744  */
46745 
46746 DUK_INTERNAL void duk_error_throw_from_negative_rc(duk_hthread *thr, duk_ret_t rc) {
46747 	DUK_ASSERT(thr != NULL);
46748 	DUK_ASSERT(rc < 0);
46749 
46750 	/*
46751 	 *  The __FILE__ and __LINE__ information is intentionally not used in the
46752 	 *  creation of the error object, as it isn't useful in the tracedata.  The
46753 	 *  tracedata still contains the function which returned the negative return
46754 	 *  code, and having the file/line of this function isn't very useful.
46755 	 *
46756 	 *  The error messages for DUK_RET_xxx shorthand are intentionally very
46757 	 *  minimal: they're only really useful for low memory targets.
46758 	 */
46759 
46760 	duk_error_raw(thr, -rc, NULL, 0, "error (rc %ld)", (long) rc);
46761 	DUK_WO_NORETURN(return;);
46762 }
46763 #line 1 "duk_hbuffer_alloc.c"
46764 /*
46765  *  duk_hbuffer allocation and freeing.
46766  */
46767 
46768 /* #include duk_internal.h -> already included */
46769 
46770 /* Allocate a new duk_hbuffer of a certain type and return a pointer to it
46771  * (NULL on error).  Write buffer data pointer to 'out_bufdata' (only if
46772  * allocation successful).
46773  */
46774 DUK_INTERNAL duk_hbuffer *duk_hbuffer_alloc(duk_heap *heap, duk_size_t size, duk_small_uint_t flags, void **out_bufdata) {
46775 	duk_hbuffer *res = NULL;
46776 	duk_size_t header_size;
46777 	duk_size_t alloc_size;
46778 
46779 	DUK_ASSERT(heap != NULL);
46780 	DUK_ASSERT(out_bufdata != NULL);
46781 
46782 	DUK_DDD(DUK_DDDPRINT("allocate hbuffer"));
46783 
46784 	/* Size sanity check.  Should not be necessary because caller is
46785 	 * required to check this, but we don't want to cause a segfault
46786 	 * if the size wraps either in duk_size_t computation or when
46787 	 * storing the size in a 16-bit field.
46788 	 */
46789 	if (size > DUK_HBUFFER_MAX_BYTELEN) {
46790 		DUK_D(DUK_DPRINT("hbuffer alloc failed: size too large: %ld", (long) size));
46791 		return NULL;  /* no need to write 'out_bufdata' */
46792 	}
46793 
46794 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
46795 		header_size = sizeof(duk_hbuffer_external);
46796 		alloc_size = sizeof(duk_hbuffer_external);
46797 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
46798 		header_size = sizeof(duk_hbuffer_dynamic);
46799 		alloc_size = sizeof(duk_hbuffer_dynamic);
46800 	} else {
46801 		header_size = sizeof(duk_hbuffer_fixed);
46802 		alloc_size = sizeof(duk_hbuffer_fixed) + size;
46803 		DUK_ASSERT(alloc_size >= sizeof(duk_hbuffer_fixed));  /* no wrapping */
46804 	}
46805 
46806 	res = (duk_hbuffer *) DUK_ALLOC(heap, alloc_size);
46807 	if (DUK_UNLIKELY(res == NULL)) {
46808 		goto alloc_error;
46809 	}
46810 
46811 	/* zero everything unless requested not to do so */
46812 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46813 	duk_memzero((void *) res,
46814 	            (flags & DUK_BUF_FLAG_NOZERO) ? header_size : alloc_size);
46815 #else
46816 	duk_memzero((void *) res, header_size);
46817 #endif
46818 
46819 	if (flags & DUK_BUF_FLAG_EXTERNAL) {
46820 		duk_hbuffer_external *h;
46821 		h = (duk_hbuffer_external *) res;
46822 		DUK_UNREF(h);
46823 		*out_bufdata = NULL;
46824 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
46825 #if defined(DUK_USE_HEAPPTR16)
46826 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
46827 #else
46828 		DUK_HBUFFER_EXTERNAL_SET_DATA_PTR(heap, h, NULL);
46829 #endif
46830 #endif
46831 		DUK_ASSERT(DUK_HBUFFER_EXTERNAL_GET_DATA_PTR(heap, h) == NULL);
46832 	} else if (flags & DUK_BUF_FLAG_DYNAMIC) {
46833 		duk_hbuffer_dynamic *h = (duk_hbuffer_dynamic *) res;
46834 		void *ptr;
46835 
46836 		if (size > 0) {
46837 			DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));  /* alloc external with size zero */
46838 			DUK_DDD(DUK_DDDPRINT("dynamic buffer with nonzero size, alloc actual buffer"));
46839 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46840 			ptr = DUK_ALLOC_ZEROED(heap, size);
46841 #else
46842 			ptr = DUK_ALLOC(heap, size);
46843 #endif
46844 			if (DUK_UNLIKELY(ptr == NULL)) {
46845 				/* Because size > 0, NULL check is correct */
46846 				goto alloc_error;
46847 			}
46848 			*out_bufdata = ptr;
46849 
46850 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, ptr);
46851 		} else {
46852 			*out_bufdata = NULL;
46853 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
46854 #if defined(DUK_USE_HEAPPTR16)
46855 /* the compressed pointer is zeroed which maps to NULL, so nothing to do. */
46856 #else
46857 			DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(heap, h, NULL);
46858 #endif
46859 #endif
46860 			DUK_ASSERT(DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, h) == NULL);
46861 		}
46862 	} else {
46863 		*out_bufdata = (void *) ((duk_hbuffer_fixed *) (void *) res + 1);
46864 	}
46865 
46866 	DUK_HBUFFER_SET_SIZE(res, size);
46867 
46868 	DUK_HEAPHDR_SET_TYPE(&res->hdr, DUK_HTYPE_BUFFER);
46869 	if (flags & DUK_BUF_FLAG_DYNAMIC) {
46870 		DUK_HBUFFER_SET_DYNAMIC(res);
46871 		if (flags & DUK_BUF_FLAG_EXTERNAL) {
46872 			DUK_HBUFFER_SET_EXTERNAL(res);
46873 		}
46874 	} else {
46875 		DUK_ASSERT(!(flags & DUK_BUF_FLAG_EXTERNAL));
46876 	}
46877         DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &res->hdr);
46878 
46879 	DUK_DDD(DUK_DDDPRINT("allocated hbuffer: %p", (void *) res));
46880 	return res;
46881 
46882  alloc_error:
46883 	DUK_DD(DUK_DDPRINT("hbuffer allocation failed"));
46884 
46885 	DUK_FREE(heap, res);
46886 	return NULL;  /* no need to write 'out_bufdata' */
46887 }
46888 
46889 /* For indirect allocs. */
46890 
46891 DUK_INTERNAL void *duk_hbuffer_get_dynalloc_ptr(duk_heap *heap, void *ud) {
46892 	duk_hbuffer_dynamic *buf = (duk_hbuffer_dynamic *) ud;
46893 	DUK_UNREF(heap);
46894 	return (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, buf);
46895 }
46896 #line 1 "duk_hbuffer_ops.c"
46897 /*
46898  *  duk_hbuffer operations such as resizing and inserting/appending data to
46899  *  a dynamic buffer.
46900  */
46901 
46902 /* #include duk_internal.h -> already included */
46903 
46904 /*
46905  *  Resizing
46906  */
46907 
46908 DUK_INTERNAL void duk_hbuffer_resize(duk_hthread *thr, duk_hbuffer_dynamic *buf, duk_size_t new_size) {
46909 	void *res;
46910 	duk_size_t prev_size;
46911 
46912 	DUK_ASSERT(thr != NULL);
46913 	DUK_ASSERT(buf != NULL);
46914 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
46915 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
46916 
46917 	/*
46918 	 *  Maximum size check
46919 	 */
46920 
46921 	if (new_size > DUK_HBUFFER_MAX_BYTELEN) {
46922 		DUK_ERROR_RANGE(thr, "buffer too long");
46923 		DUK_WO_NORETURN(return;);
46924 	}
46925 
46926 	/*
46927 	 *  Note: use indirect realloc variant just in case mark-and-sweep
46928 	 *  (finalizers) might resize this same buffer during garbage
46929 	 *  collection.
46930 	 */
46931 
46932 	res = DUK_REALLOC_INDIRECT(thr->heap, duk_hbuffer_get_dynalloc_ptr, (void *) buf, new_size);
46933 	if (DUK_LIKELY(res != NULL || new_size == 0)) {
46934 		/* 'res' may be NULL if new allocation size is 0. */
46935 
46936 		DUK_DDD(DUK_DDDPRINT("resized dynamic buffer %p:%ld -> %p:%ld",
46937 		                     (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, buf),
46938 		                     (long) DUK_HBUFFER_DYNAMIC_GET_SIZE(buf),
46939 		                     (void *) res,
46940 		                     (long) new_size));
46941 
46942 		/*
46943 		 *  The entire allocated buffer area, regardless of actual used
46944 		 *  size, is kept zeroed in resizes for simplicity.  If the buffer
46945 		 *  is grown, zero the new part.
46946 		 */
46947 
46948 		prev_size = DUK_HBUFFER_DYNAMIC_GET_SIZE(buf);
46949 		if (new_size > prev_size) {
46950 			DUK_ASSERT(new_size - prev_size > 0);
46951 #if defined(DUK_USE_ZERO_BUFFER_DATA)
46952 			duk_memzero((void *) ((char *) res + prev_size),
46953 			            (duk_size_t) (new_size - prev_size));
46954 #endif
46955 		}
46956 
46957 		DUK_HBUFFER_DYNAMIC_SET_SIZE(buf, new_size);
46958 		DUK_HBUFFER_DYNAMIC_SET_DATA_PTR(thr->heap, buf, res);
46959 	} else {
46960 		DUK_ERROR_ALLOC_FAILED(thr);
46961 		DUK_WO_NORETURN(return;);
46962 	}
46963 
46964 	DUK_ASSERT(res != NULL || new_size == 0);
46965 }
46966 
46967 DUK_INTERNAL void duk_hbuffer_reset(duk_hthread *thr, duk_hbuffer_dynamic *buf) {
46968 	DUK_ASSERT(thr != NULL);
46969 	DUK_ASSERT(buf != NULL);
46970 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(buf));
46971 	DUK_ASSERT(!DUK_HBUFFER_HAS_EXTERNAL(buf));
46972 
46973 	duk_hbuffer_resize(thr, buf, 0);
46974 }
46975 /* #include duk_internal.h -> already included */
46976 #line 2 "duk_hbufobj_misc.c"
46977 
46978 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
46979 DUK_INTERNAL duk_uint_t duk_hbufobj_clamp_bytelength(duk_hbufobj *h_bufobj, duk_uint_t len) {
46980 	duk_uint_t buf_size;
46981 	duk_uint_t buf_avail;
46982 
46983 	DUK_ASSERT(h_bufobj != NULL);
46984 	DUK_ASSERT(h_bufobj->buf != NULL);
46985 
46986 	buf_size = (duk_uint_t) DUK_HBUFFER_GET_SIZE(h_bufobj->buf);
46987 	if (h_bufobj->offset > buf_size) {
46988 		/* Slice starting point is beyond current length. */
46989 		return 0;
46990 	}
46991 	buf_avail = buf_size - h_bufobj->offset;
46992 
46993 	return buf_avail >= len ? len : buf_avail;
46994 }
46995 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
46996 #line 1 "duk_heap_alloc.c"
46997 /*
46998  *  duk_heap allocation and freeing.
46999  */
47000 
47001 /* #include duk_internal.h -> already included */
47002 
47003 #if defined(DUK_USE_ROM_STRINGS)
47004 /* Fixed seed value used with ROM strings. */
47005 #define DUK__FIXED_HASH_SEED       0xabcd1234
47006 #endif
47007 
47008 /*
47009  *  Free a heap object.
47010  *
47011  *  Free heap object and its internal (non-heap) pointers.  Assumes that
47012  *  caller has removed the object from heap allocated list or the string
47013  *  intern table, and any weak references (which strings may have) have
47014  *  been already dealt with.
47015  */
47016 
47017 DUK_INTERNAL void duk_free_hobject(duk_heap *heap, duk_hobject *h) {
47018 	DUK_ASSERT(heap != NULL);
47019 	DUK_ASSERT(h != NULL);
47020 
47021 	DUK_FREE(heap, DUK_HOBJECT_GET_PROPS(heap, h));
47022 
47023 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
47024 		duk_hcompfunc *f = (duk_hcompfunc *) h;
47025 		DUK_UNREF(f);
47026 		/* Currently nothing to free; 'data' is a heap object */
47027 	} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
47028 		duk_hnatfunc *f = (duk_hnatfunc *) h;
47029 		DUK_UNREF(f);
47030 		/* Currently nothing to free */
47031 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
47032 		duk_hthread *t = (duk_hthread *) h;
47033 		duk_activation *act;
47034 
47035 		DUK_FREE(heap, t->valstack);
47036 
47037 		/* Don't free h->resumer because it exists in the heap.
47038 		 * Callstack entries also contain function pointers which
47039 		 * are not freed for the same reason.  They are decref
47040 		 * finalized and the targets are freed if necessary based
47041 		 * on their refcount (or reachability).
47042 		 */
47043 		for (act = t->callstack_curr; act != NULL;) {
47044 			duk_activation *act_next;
47045 			duk_catcher *cat;
47046 
47047 			for (cat = act->cat; cat != NULL;) {
47048 				duk_catcher *cat_next;
47049 
47050 				cat_next = cat->parent;
47051 				DUK_FREE(heap, (void *) cat);
47052 				cat = cat_next;
47053 			}
47054 
47055 			act_next = act->parent;
47056 			DUK_FREE(heap, (void *) act);
47057 			act = act_next;
47058 		}
47059 
47060 		/* XXX: with 'caller' property the callstack would need
47061 		 * to be unwound to update the 'caller' properties of
47062 		 * functions in the callstack.
47063 		 */
47064 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
47065 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
47066 
47067 		DUK_FREE(heap, f->args);
47068 	}
47069 
47070 	DUK_FREE(heap, (void *) h);
47071 }
47072 
47073 DUK_INTERNAL void duk_free_hbuffer(duk_heap *heap, duk_hbuffer *h) {
47074 	DUK_ASSERT(heap != NULL);
47075 	DUK_ASSERT(h != NULL);
47076 
47077 	if (DUK_HBUFFER_HAS_DYNAMIC(h) && !DUK_HBUFFER_HAS_EXTERNAL(h)) {
47078 		duk_hbuffer_dynamic *g = (duk_hbuffer_dynamic *) h;
47079 		DUK_DDD(DUK_DDDPRINT("free dynamic buffer %p", (void *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g)));
47080 		DUK_FREE(heap, DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(heap, g));
47081 	}
47082 	DUK_FREE(heap, (void *) h);
47083 }
47084 
47085 DUK_INTERNAL void duk_free_hstring(duk_heap *heap, duk_hstring *h) {
47086 	DUK_ASSERT(heap != NULL);
47087 	DUK_ASSERT(h != NULL);
47088 
47089 	DUK_UNREF(heap);
47090 	DUK_UNREF(h);
47091 
47092 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_FREE)
47093 	if (DUK_HSTRING_HAS_EXTDATA(h)) {
47094 		DUK_DDD(DUK_DDDPRINT("free extstr: hstring %!O, extdata: %p",
47095 		                     h, DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h)));
47096 		DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) DUK_HSTRING_GET_EXTDATA((duk_hstring_external *) h));
47097 	}
47098 #endif
47099 	DUK_FREE(heap, (void *) h);
47100 }
47101 
47102 DUK_INTERNAL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr) {
47103 	DUK_ASSERT(heap);
47104 	DUK_ASSERT(hdr);
47105 
47106 	DUK_DDD(DUK_DDDPRINT("free heaphdr %p, htype %ld", (void *) hdr, (long) DUK_HEAPHDR_GET_TYPE(hdr)));
47107 
47108 	switch (DUK_HEAPHDR_GET_TYPE(hdr)) {
47109 	case DUK_HTYPE_STRING:
47110 		duk_free_hstring(heap, (duk_hstring *) hdr);
47111 		break;
47112 	case DUK_HTYPE_OBJECT:
47113 		duk_free_hobject(heap, (duk_hobject *) hdr);
47114 		break;
47115 	default:
47116 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) == DUK_HTYPE_BUFFER);
47117 		duk_free_hbuffer(heap, (duk_hbuffer *) hdr);
47118 	}
47119 
47120 }
47121 
47122 /*
47123  *  Free the heap.
47124  *
47125  *  Frees heap-related non-heap-tracked allocations such as the
47126  *  string intern table; then frees the heap allocated objects;
47127  *  and finally frees the heap structure itself.  Reference counts
47128  *  and GC markers are ignored (and not updated) in this process,
47129  *  and finalizers won't be called.
47130  *
47131  *  The heap pointer and heap object pointers must not be used
47132  *  after this call.
47133  */
47134 
47135 #if defined(DUK_USE_CACHE_ACTIVATION)
47136 DUK_LOCAL duk_size_t duk__heap_free_activation_freelist(duk_heap *heap) {
47137 	duk_activation *act;
47138 	duk_activation *act_next;
47139 	duk_size_t count_act = 0;
47140 
47141 	for (act = heap->activation_free; act != NULL;) {
47142 		act_next = act->parent;
47143 		DUK_FREE(heap, (void *) act);
47144 		act = act_next;
47145 #if defined(DUK_USE_DEBUG)
47146 		count_act++;
47147 #endif
47148 	}
47149 	heap->activation_free = NULL;  /* needed when called from mark-and-sweep */
47150 	return count_act;
47151 }
47152 #endif  /* DUK_USE_CACHE_ACTIVATION */
47153 
47154 #if defined(DUK_USE_CACHE_CATCHER)
47155 DUK_LOCAL duk_size_t duk__heap_free_catcher_freelist(duk_heap *heap) {
47156 	duk_catcher *cat;
47157 	duk_catcher *cat_next;
47158 	duk_size_t count_cat = 0;
47159 
47160 	for (cat = heap->catcher_free; cat != NULL;) {
47161 		cat_next = cat->parent;
47162 		DUK_FREE(heap, (void *) cat);
47163 		cat = cat_next;
47164 #if defined(DUK_USE_DEBUG)
47165 		count_cat++;
47166 #endif
47167 	}
47168 	heap->catcher_free = NULL;  /* needed when called from mark-and-sweep */
47169 
47170 	return count_cat;
47171 }
47172 #endif  /* DUK_USE_CACHE_CATCHER */
47173 
47174 DUK_INTERNAL void duk_heap_free_freelists(duk_heap *heap) {
47175 	duk_size_t count_act = 0;
47176 	duk_size_t count_cat = 0;
47177 
47178 #if defined(DUK_USE_CACHE_ACTIVATION)
47179 	count_act = duk__heap_free_activation_freelist(heap);
47180 #endif
47181 #if defined(DUK_USE_CACHE_CATCHER)
47182 	count_cat = duk__heap_free_catcher_freelist(heap);
47183 #endif
47184 	DUK_UNREF(heap);
47185 	DUK_UNREF(count_act);
47186 	DUK_UNREF(count_cat);
47187 
47188 	DUK_D(DUK_DPRINT("freed %ld activation freelist entries, %ld catcher freelist entries",
47189 	                 (long) count_act, (long) count_cat));
47190 }
47191 
47192 DUK_LOCAL void duk__free_allocated(duk_heap *heap) {
47193 	duk_heaphdr *curr;
47194 	duk_heaphdr *next;
47195 
47196 	curr = heap->heap_allocated;
47197 	while (curr) {
47198 		/* We don't log or warn about freeing zero refcount objects
47199 		 * because they may happen with finalizer processing.
47200 		 */
47201 
47202 		DUK_DDD(DUK_DDDPRINT("FINALFREE (allocated): %!iO",
47203 		                     (duk_heaphdr *) curr));
47204 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47205 		duk_heap_free_heaphdr_raw(heap, curr);
47206 		curr = next;
47207 	}
47208 }
47209 
47210 #if defined(DUK_USE_FINALIZER_SUPPORT)
47211 DUK_LOCAL void duk__free_finalize_list(duk_heap *heap) {
47212 	duk_heaphdr *curr;
47213 	duk_heaphdr *next;
47214 
47215 	curr = heap->finalize_list;
47216 	while (curr) {
47217 		DUK_DDD(DUK_DDDPRINT("FINALFREE (finalize_list): %!iO",
47218 		                     (duk_heaphdr *) curr));
47219 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
47220 		duk_heap_free_heaphdr_raw(heap, curr);
47221 		curr = next;
47222 	}
47223 }
47224 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47225 
47226 DUK_LOCAL void duk__free_stringtable(duk_heap *heap) {
47227 	/* strings are only tracked by stringtable */
47228 	duk_heap_strtable_free(heap);
47229 }
47230 
47231 #if defined(DUK_USE_FINALIZER_SUPPORT)
47232 DUK_LOCAL void duk__free_run_finalizers(duk_heap *heap) {
47233 	duk_heaphdr *curr;
47234 	duk_uint_t round_no;
47235 	duk_size_t count_all;
47236 	duk_size_t count_finalized;
47237 	duk_size_t curr_limit;
47238 
47239 	DUK_ASSERT(heap != NULL);
47240 
47241 #if defined(DUK_USE_REFERENCE_COUNTING)
47242 	DUK_ASSERT(heap->refzero_list == NULL);  /* refzero not running -> must be empty */
47243 #endif
47244 	DUK_ASSERT(heap->finalize_list == NULL);  /* mark-and-sweep last pass */
47245 
47246 	if (heap->heap_thread == NULL) {
47247 		/* May happen when heap allocation fails right off.  There
47248 		 * cannot be any finalizable objects in this case.
47249 		 */
47250 		DUK_D(DUK_DPRINT("no heap_thread in heap destruct, assume no finalizable objects"));
47251 		return;
47252 	}
47253 
47254 	/* Prevent finalize_list processing and mark-and-sweep entirely.
47255 	 * Setting ms_running = 1 also prevents refzero handling from moving
47256 	 * objects away from the heap_allocated list (the flag name is a bit
47257 	 * misleading here).
47258 	 */
47259 	DUK_ASSERT(heap->pf_prevent_count == 0);
47260 	heap->pf_prevent_count = 1;
47261 	DUK_ASSERT(heap->ms_running == 0);
47262 	heap->ms_running = 1;
47263 	DUK_ASSERT(heap->ms_prevent_count == 0);
47264 	heap->ms_prevent_count = 1;  /* Bump, because mark-and-sweep assumes it's bumped when ms_running is set. */
47265 
47266 	curr_limit = 0;  /* suppress warning, not used */
47267 	for (round_no = 0; ; round_no++) {
47268 		curr = heap->heap_allocated;
47269 		count_all = 0;
47270 		count_finalized = 0;
47271 		while (curr) {
47272 			count_all++;
47273 			if (DUK_HEAPHDR_IS_OBJECT(curr)) {
47274 				/* Only objects in heap_allocated may have finalizers.  Check that
47275 				 * the object itself has a _Finalizer property (own or inherited)
47276 				 * so that we don't execute finalizers for e.g. Proxy objects.
47277 				 */
47278 				DUK_ASSERT(curr != NULL);
47279 
47280 				if (DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) curr)) {
47281 					if (!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) curr)) {
47282 						DUK_ASSERT(DUK_HEAP_HAS_FINALIZER_NORESCUE(heap));  /* maps to finalizer 2nd argument */
47283 						duk_heap_run_finalizer(heap, (duk_hobject *) curr);
47284 						count_finalized++;
47285 					}
47286 				}
47287 			}
47288 			curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
47289 		}
47290 
47291 		/* Each round of finalizer execution may spawn new finalizable objects
47292 		 * which is normal behavior for some applications.  Allow multiple
47293 		 * rounds of finalization, but use a shrinking limit based on the
47294 		 * first round to detect the case where a runaway finalizer creates
47295 		 * an unbounded amount of new finalizable objects.  Finalizer rescue
47296 		 * is not supported: the semantics are unclear because most of the
47297 		 * objects being finalized here are already reachable.  The finalizer
47298 		 * is given a boolean to indicate that rescue is not possible.
47299 		 *
47300 		 * See discussion in: https://github.com/svaarala/duktape/pull/473
47301 		 */
47302 
47303 		if (round_no == 0) {
47304 			/* Cannot wrap: each object is at least 8 bytes so count is
47305 			 * at most 1/8 of that.
47306 			 */
47307 			curr_limit = count_all * 2;
47308 		} else {
47309 			curr_limit = (curr_limit * 3) / 4;   /* Decrease by 25% every round */
47310 		}
47311 		DUK_D(DUK_DPRINT("finalizer round %ld complete, %ld objects, tried to execute %ld finalizers, current limit is %ld",
47312 		                 (long) round_no, (long) count_all, (long) count_finalized, (long) curr_limit));
47313 
47314 		if (count_finalized == 0) {
47315 			DUK_D(DUK_DPRINT("no more finalizable objects, forced finalization finished"));
47316 			break;
47317 		}
47318 		if (count_finalized >= curr_limit) {
47319 			DUK_D(DUK_DPRINT("finalizer count above limit, potentially runaway finalizer; skip remaining finalizers"));
47320 			break;
47321 		}
47322 	}
47323 
47324 	DUK_ASSERT(heap->ms_running == 1);
47325 	heap->ms_running = 0;
47326 	DUK_ASSERT(heap->pf_prevent_count == 1);
47327 	heap->pf_prevent_count = 0;
47328 }
47329 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47330 
47331 DUK_INTERNAL void duk_heap_free(duk_heap *heap) {
47332 	DUK_D(DUK_DPRINT("free heap: %p", (void *) heap));
47333 
47334 #if defined(DUK_USE_DEBUG)
47335 	duk_heap_strtable_dump(heap);
47336 #endif
47337 
47338 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47339 	/* Detach a debugger if attached (can be called multiple times)
47340 	 * safely.
47341 	 */
47342 	/* XXX: Add a flag to reject an attempt to re-attach?  Otherwise
47343 	 * the detached callback may immediately reattach.
47344 	 */
47345 	duk_debug_do_detach(heap);
47346 #endif
47347 
47348 	/* Execute finalizers before freeing the heap, even for reachable
47349 	 * objects.  This gives finalizers the chance to free any native
47350 	 * resources like file handles, allocations made outside Duktape,
47351 	 * etc.  This is quite tricky to get right, so that all finalizer
47352 	 * guarantees are honored.
47353 	 *
47354 	 * Run mark-and-sweep a few times just in case (unreachable object
47355 	 * finalizers run already here).  The last round must rescue objects
47356 	 * from the previous round without running any more finalizers.  This
47357 	 * ensures rescued objects get their FINALIZED flag cleared so that
47358 	 * their finalizer is called once more in forced finalization to
47359 	 * satisfy finalizer guarantees.  However, we don't want to run any
47360 	 * more finalizers because that'd required one more loop, and so on.
47361 	 *
47362 	 * XXX: this perhaps requires an execution time limit.
47363 	 */
47364 	DUK_D(DUK_DPRINT("execute finalizers before freeing heap"));
47365 	DUK_ASSERT(heap->pf_skip_finalizers == 0);
47366 	DUK_D(DUK_DPRINT("forced gc #1 in heap destruction"));
47367 	duk_heap_mark_and_sweep(heap, 0);
47368 	DUK_D(DUK_DPRINT("forced gc #2 in heap destruction"));
47369 	duk_heap_mark_and_sweep(heap, 0);
47370 	DUK_D(DUK_DPRINT("forced gc #3 in heap destruction (don't run finalizers)"));
47371 	heap->pf_skip_finalizers = 1;
47372 	duk_heap_mark_and_sweep(heap, 0);  /* Skip finalizers; queue finalizable objects to heap_allocated. */
47373 
47374 	/* There are never objects in refzero_list at this point, or at any
47375 	 * point beyond a DECREF (even a DECREF_NORZ).  Since Duktape 2.1
47376 	 * refzero_list processing is side effect free, so it is always
47377 	 * processed to completion by a DECREF initially triggering a zero
47378 	 * refcount.
47379 	 */
47380 #if defined(DUK_USE_REFERENCE_COUNTING)
47381 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47382 #endif
47383 #if defined(DUK_USE_FINALIZER_SUPPORT)
47384 	DUK_ASSERT(heap->finalize_list == NULL);  /* Last mark-and-sweep with skip_finalizers. */
47385 #endif
47386 
47387 #if defined(DUK_USE_FINALIZER_SUPPORT)
47388 	DUK_D(DUK_DPRINT("run finalizers for remaining finalizable objects"));
47389 	DUK_HEAP_SET_FINALIZER_NORESCUE(heap);  /* Rescue no longer supported. */
47390 	duk__free_run_finalizers(heap);
47391 #endif  /* DUK_USE_FINALIZER_SUPPORT */
47392 
47393 	/* Note: heap->heap_thread, heap->curr_thread, and heap->heap_object
47394 	 * are on the heap allocated list.
47395 	 */
47396 
47397 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
47398 	duk_heap_free_freelists(heap);
47399 
47400 	DUK_D(DUK_DPRINT("freeing heap_allocated of heap: %p", (void *) heap));
47401 	duk__free_allocated(heap);
47402 
47403 #if defined(DUK_USE_REFERENCE_COUNTING)
47404 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always processed to completion inline. */
47405 #endif
47406 
47407 #if defined(DUK_USE_FINALIZER_SUPPORT)
47408 	DUK_D(DUK_DPRINT("freeing finalize_list of heap: %p", (void *) heap));
47409 	duk__free_finalize_list(heap);
47410 #endif
47411 
47412 	DUK_D(DUK_DPRINT("freeing string table of heap: %p", (void *) heap));
47413 	duk__free_stringtable(heap);
47414 
47415 	DUK_D(DUK_DPRINT("freeing heap structure: %p", (void *) heap));
47416 	heap->free_func(heap->heap_udata, heap);
47417 }
47418 
47419 /*
47420  *  Allocate a heap.
47421  *
47422  *  String table is initialized with built-in strings from genbuiltins.py,
47423  *  either by dynamically creating the strings or by referring to ROM strings.
47424  */
47425 
47426 #if defined(DUK_USE_ROM_STRINGS)
47427 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47428 #if defined(DUK_USE_ASSERTIONS)
47429 	duk_small_uint_t i;
47430 #endif
47431 
47432 	DUK_UNREF(heap);
47433 
47434 	/* With ROM-based strings, heap->strs[] and thr->strs[] are omitted
47435 	 * so nothing to initialize for strs[].
47436 	 */
47437 
47438 #if defined(DUK_USE_ASSERTIONS)
47439 	for (i = 0; i < sizeof(duk_rom_strings_lookup) / sizeof(const duk_hstring *); i++) {
47440 		const duk_hstring *h;
47441 		duk_uint32_t hash;
47442 
47443 		h = duk_rom_strings_lookup[i];
47444 		while (h != NULL) {
47445 			hash = duk_heap_hashstring(heap, (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
47446 			DUK_DD(DUK_DDPRINT("duk_rom_strings_lookup[%d] -> hash 0x%08lx, computed 0x%08lx",
47447 			                   (int) i, (unsigned long) DUK_HSTRING_GET_HASH(h), (unsigned long) hash));
47448 			DUK_ASSERT(hash == (duk_uint32_t) DUK_HSTRING_GET_HASH(h));
47449 
47450 			h = (const duk_hstring *) h->hdr.h_next;
47451 		}
47452 	}
47453 #endif
47454 	return 1;
47455 }
47456 #else  /* DUK_USE_ROM_STRINGS */
47457 
47458 DUK_LOCAL duk_bool_t duk__init_heap_strings(duk_heap *heap) {
47459 	duk_bitdecoder_ctx bd_ctx;
47460 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
47461 	duk_small_uint_t i;
47462 
47463 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
47464 	bd->data = (const duk_uint8_t *) duk_strings_data;
47465 	bd->length = (duk_size_t) DUK_STRDATA_DATA_LENGTH;
47466 
47467 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
47468 		duk_uint8_t tmp[DUK_STRDATA_MAX_STRLEN];
47469 		duk_small_uint_t len;
47470 		duk_hstring *h;
47471 
47472 		len = duk_bd_decode_bitpacked_string(bd, tmp);
47473 
47474 		/* No need to length check string: it will never exceed even
47475 		 * the 16-bit length maximum.
47476 		 */
47477 		DUK_ASSERT(len <= 0xffffUL);
47478 		DUK_DDD(DUK_DDDPRINT("intern built-in string %ld", (long) i));
47479 		h = duk_heap_strtable_intern(heap, tmp, len);
47480 		if (!h) {
47481 			goto failed;
47482 		}
47483 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
47484 
47485 		/* Special flags checks.  Since these strings are always
47486 		 * reachable and a string cannot appear twice in the string
47487 		 * table, there's no need to check/set these flags elsewhere.
47488 		 * The 'internal' flag is set by string intern code.
47489 		 */
47490 		if (i == DUK_STRIDX_EVAL || i == DUK_STRIDX_LC_ARGUMENTS) {
47491 			DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(h);
47492 		}
47493 		if (i >= DUK_STRIDX_START_RESERVED && i < DUK_STRIDX_END_RESERVED) {
47494 			DUK_HSTRING_SET_RESERVED_WORD(h);
47495 			if (i >= DUK_STRIDX_START_STRICT_RESERVED) {
47496 				DUK_HSTRING_SET_STRICT_RESERVED_WORD(h);
47497 			}
47498 		}
47499 
47500 		DUK_DDD(DUK_DDDPRINT("interned: %!O", (duk_heaphdr *) h));
47501 
47502 		/* XXX: The incref macro takes a thread pointer but doesn't
47503 		 * use it right now.
47504 		 */
47505 		DUK_HSTRING_INCREF(_never_referenced_, h);
47506 
47507 #if defined(DUK_USE_HEAPPTR16)
47508 		heap->strs16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
47509 #else
47510 		heap->strs[i] = h;
47511 #endif
47512 	}
47513 
47514 	return 1;
47515 
47516  failed:
47517 	return 0;
47518 }
47519 #endif  /* DUK_USE_ROM_STRINGS */
47520 
47521 DUK_LOCAL duk_bool_t duk__init_heap_thread(duk_heap *heap) {
47522 	duk_hthread *thr;
47523 
47524 	DUK_D(DUK_DPRINT("heap init: alloc heap thread"));
47525 	thr = duk_hthread_alloc_unchecked(heap,
47526 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
47527 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_THREAD));
47528 	if (thr == NULL) {
47529 		DUK_D(DUK_DPRINT("failed to alloc heap_thread"));
47530 		return 0;
47531 	}
47532 	thr->state = DUK_HTHREAD_STATE_INACTIVE;
47533 #if defined(DUK_USE_ROM_STRINGS)
47534 	/* No strs[] pointer. */
47535 #else  /* DUK_USE_ROM_STRINGS */
47536 #if defined(DUK_USE_HEAPPTR16)
47537 	thr->strs16 = heap->strs16;
47538 #else
47539 	thr->strs = heap->strs;
47540 #endif
47541 #endif  /* DUK_USE_ROM_STRINGS */
47542 
47543 	heap->heap_thread = thr;
47544 	DUK_HTHREAD_INCREF(thr, thr);  /* Note: first argument not really used */
47545 
47546 	/* 'thr' is now reachable */
47547 
47548 	DUK_D(DUK_DPRINT("heap init: init heap thread stacks"));
47549 	if (!duk_hthread_init_stacks(heap, thr)) {
47550 		return 0;
47551 	}
47552 
47553 	/* XXX: this may now fail, and is not handled correctly */
47554 	duk_hthread_create_builtin_objects(thr);
47555 
47556 	/* default prototype */
47557 	DUK_HOBJECT_SET_PROTOTYPE_INIT_INCREF(thr, (duk_hobject *) thr, thr->builtins[DUK_BIDX_THREAD_PROTOTYPE]);
47558 
47559 	return 1;
47560 }
47561 
47562 #if defined(DUK_USE_DEBUG)
47563 #define DUK__DUMPSZ(t)  do { \
47564 		DUK_D(DUK_DPRINT("" #t "=%ld", (long) sizeof(t))); \
47565 	} while (0)
47566 
47567 /* These is not 100% because format would need to be non-portable "long long".
47568  * Also print out as doubles to catch cases where the "long" type is not wide
47569  * enough; the limits will then not be printed accurately but the magnitude
47570  * will be correct.
47571  */
47572 #define DUK__DUMPLM_SIGNED_RAW(t,a,b)  do { \
47573 		DUK_D(DUK_DPRINT(t "=[%ld,%ld]=[%lf,%lf]", \
47574 		                 (long) (a), (long) (b), \
47575 		                 (double) (a), (double) (b))); \
47576 	} while (0)
47577 #define DUK__DUMPLM_UNSIGNED_RAW(t,a,b)  do { \
47578 		DUK_D(DUK_DPRINT(t "=[%lu,%lu]=[%lf,%lf]", \
47579 		                 (unsigned long) (a), (unsigned long) (b), \
47580 		                 (double) (a), (double) (b))); \
47581 	} while (0)
47582 #define DUK__DUMPLM_SIGNED(t)  do { \
47583 		DUK__DUMPLM_SIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47584 	} while (0)
47585 #define DUK__DUMPLM_UNSIGNED(t)  do { \
47586 		DUK__DUMPLM_UNSIGNED_RAW("DUK_" #t "_{MIN,MAX}", DUK_##t##_MIN, DUK_##t##_MAX); \
47587 	} while (0)
47588 
47589 DUK_LOCAL void duk__dump_type_sizes(void) {
47590 	DUK_D(DUK_DPRINT("sizeof()"));
47591 
47592 	/* basic platform types */
47593 	DUK__DUMPSZ(char);
47594 	DUK__DUMPSZ(short);
47595 	DUK__DUMPSZ(int);
47596 	DUK__DUMPSZ(long);
47597 	DUK__DUMPSZ(double);
47598 	DUK__DUMPSZ(void *);
47599 	DUK__DUMPSZ(size_t);
47600 
47601 	/* basic types from duk_features.h */
47602 	DUK__DUMPSZ(duk_uint8_t);
47603 	DUK__DUMPSZ(duk_int8_t);
47604 	DUK__DUMPSZ(duk_uint16_t);
47605 	DUK__DUMPSZ(duk_int16_t);
47606 	DUK__DUMPSZ(duk_uint32_t);
47607 	DUK__DUMPSZ(duk_int32_t);
47608 	DUK__DUMPSZ(duk_uint64_t);
47609 	DUK__DUMPSZ(duk_int64_t);
47610 	DUK__DUMPSZ(duk_uint_least8_t);
47611 	DUK__DUMPSZ(duk_int_least8_t);
47612 	DUK__DUMPSZ(duk_uint_least16_t);
47613 	DUK__DUMPSZ(duk_int_least16_t);
47614 	DUK__DUMPSZ(duk_uint_least32_t);
47615 	DUK__DUMPSZ(duk_int_least32_t);
47616 #if defined(DUK_USE_64BIT_OPS)
47617 	DUK__DUMPSZ(duk_uint_least64_t);
47618 	DUK__DUMPSZ(duk_int_least64_t);
47619 #endif
47620 	DUK__DUMPSZ(duk_uint_fast8_t);
47621 	DUK__DUMPSZ(duk_int_fast8_t);
47622 	DUK__DUMPSZ(duk_uint_fast16_t);
47623 	DUK__DUMPSZ(duk_int_fast16_t);
47624 	DUK__DUMPSZ(duk_uint_fast32_t);
47625 	DUK__DUMPSZ(duk_int_fast32_t);
47626 #if defined(DUK_USE_64BIT_OPS)
47627 	DUK__DUMPSZ(duk_uint_fast64_t);
47628 	DUK__DUMPSZ(duk_int_fast64_t);
47629 #endif
47630 	DUK__DUMPSZ(duk_uintptr_t);
47631 	DUK__DUMPSZ(duk_intptr_t);
47632 	DUK__DUMPSZ(duk_uintmax_t);
47633 	DUK__DUMPSZ(duk_intmax_t);
47634 	DUK__DUMPSZ(duk_double_t);
47635 
47636 	/* important chosen base types */
47637 	DUK__DUMPSZ(duk_int_t);
47638 	DUK__DUMPSZ(duk_uint_t);
47639 	DUK__DUMPSZ(duk_int_fast_t);
47640 	DUK__DUMPSZ(duk_uint_fast_t);
47641 	DUK__DUMPSZ(duk_small_int_t);
47642 	DUK__DUMPSZ(duk_small_uint_t);
47643 	DUK__DUMPSZ(duk_small_int_fast_t);
47644 	DUK__DUMPSZ(duk_small_uint_fast_t);
47645 
47646 	/* some derived types */
47647 	DUK__DUMPSZ(duk_codepoint_t);
47648 	DUK__DUMPSZ(duk_ucodepoint_t);
47649 	DUK__DUMPSZ(duk_idx_t);
47650 	DUK__DUMPSZ(duk_errcode_t);
47651 	DUK__DUMPSZ(duk_uarridx_t);
47652 
47653 	/* tval */
47654 	DUK__DUMPSZ(duk_double_union);
47655 	DUK__DUMPSZ(duk_tval);
47656 
47657 	/* structs from duk_forwdecl.h */
47658 	DUK__DUMPSZ(duk_jmpbuf);  /* just one 'int' for C++ exceptions */
47659 	DUK__DUMPSZ(duk_heaphdr);
47660 	DUK__DUMPSZ(duk_heaphdr_string);
47661 	DUK__DUMPSZ(duk_hstring);
47662 	DUK__DUMPSZ(duk_hstring_external);
47663 	DUK__DUMPSZ(duk_hobject);
47664 	DUK__DUMPSZ(duk_harray);
47665 	DUK__DUMPSZ(duk_hcompfunc);
47666 	DUK__DUMPSZ(duk_hnatfunc);
47667 	DUK__DUMPSZ(duk_hdecenv);
47668 	DUK__DUMPSZ(duk_hobjenv);
47669 	DUK__DUMPSZ(duk_hthread);
47670 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
47671 	DUK__DUMPSZ(duk_hbufobj);
47672 #endif
47673 	DUK__DUMPSZ(duk_hproxy);
47674 	DUK__DUMPSZ(duk_hbuffer);
47675 	DUK__DUMPSZ(duk_hbuffer_fixed);
47676 	DUK__DUMPSZ(duk_hbuffer_dynamic);
47677 	DUK__DUMPSZ(duk_hbuffer_external);
47678 	DUK__DUMPSZ(duk_propaccessor);
47679 	DUK__DUMPSZ(duk_propvalue);
47680 	DUK__DUMPSZ(duk_propdesc);
47681 	DUK__DUMPSZ(duk_heap);
47682 	DUK__DUMPSZ(duk_activation);
47683 	DUK__DUMPSZ(duk_catcher);
47684 	DUK__DUMPSZ(duk_strcache_entry);
47685 	DUK__DUMPSZ(duk_litcache_entry);
47686 	DUK__DUMPSZ(duk_ljstate);
47687 	DUK__DUMPSZ(duk_fixedbuffer);
47688 	DUK__DUMPSZ(duk_bitdecoder_ctx);
47689 	DUK__DUMPSZ(duk_bitencoder_ctx);
47690 	DUK__DUMPSZ(duk_token);
47691 	DUK__DUMPSZ(duk_re_token);
47692 	DUK__DUMPSZ(duk_lexer_point);
47693 	DUK__DUMPSZ(duk_lexer_ctx);
47694 	DUK__DUMPSZ(duk_compiler_instr);
47695 	DUK__DUMPSZ(duk_compiler_func);
47696 	DUK__DUMPSZ(duk_compiler_ctx);
47697 	DUK__DUMPSZ(duk_re_matcher_ctx);
47698 	DUK__DUMPSZ(duk_re_compiler_ctx);
47699 }
47700 DUK_LOCAL void duk__dump_type_limits(void) {
47701 	DUK_D(DUK_DPRINT("limits"));
47702 
47703 	/* basic types */
47704 	DUK__DUMPLM_SIGNED(INT8);
47705 	DUK__DUMPLM_UNSIGNED(UINT8);
47706 	DUK__DUMPLM_SIGNED(INT_FAST8);
47707 	DUK__DUMPLM_UNSIGNED(UINT_FAST8);
47708 	DUK__DUMPLM_SIGNED(INT_LEAST8);
47709 	DUK__DUMPLM_UNSIGNED(UINT_LEAST8);
47710 	DUK__DUMPLM_SIGNED(INT16);
47711 	DUK__DUMPLM_UNSIGNED(UINT16);
47712 	DUK__DUMPLM_SIGNED(INT_FAST16);
47713 	DUK__DUMPLM_UNSIGNED(UINT_FAST16);
47714 	DUK__DUMPLM_SIGNED(INT_LEAST16);
47715 	DUK__DUMPLM_UNSIGNED(UINT_LEAST16);
47716 	DUK__DUMPLM_SIGNED(INT32);
47717 	DUK__DUMPLM_UNSIGNED(UINT32);
47718 	DUK__DUMPLM_SIGNED(INT_FAST32);
47719 	DUK__DUMPLM_UNSIGNED(UINT_FAST32);
47720 	DUK__DUMPLM_SIGNED(INT_LEAST32);
47721 	DUK__DUMPLM_UNSIGNED(UINT_LEAST32);
47722 #if defined(DUK_USE_64BIT_OPS)
47723 	DUK__DUMPLM_SIGNED(INT64);
47724 	DUK__DUMPLM_UNSIGNED(UINT64);
47725 	DUK__DUMPLM_SIGNED(INT_FAST64);
47726 	DUK__DUMPLM_UNSIGNED(UINT_FAST64);
47727 	DUK__DUMPLM_SIGNED(INT_LEAST64);
47728 	DUK__DUMPLM_UNSIGNED(UINT_LEAST64);
47729 #endif
47730 	DUK__DUMPLM_SIGNED(INTPTR);
47731 	DUK__DUMPLM_UNSIGNED(UINTPTR);
47732 	DUK__DUMPLM_SIGNED(INTMAX);
47733 	DUK__DUMPLM_UNSIGNED(UINTMAX);
47734 
47735 	/* derived types */
47736 	DUK__DUMPLM_SIGNED(INT);
47737 	DUK__DUMPLM_UNSIGNED(UINT);
47738 	DUK__DUMPLM_SIGNED(INT_FAST);
47739 	DUK__DUMPLM_UNSIGNED(UINT_FAST);
47740 	DUK__DUMPLM_SIGNED(SMALL_INT);
47741 	DUK__DUMPLM_UNSIGNED(SMALL_UINT);
47742 	DUK__DUMPLM_SIGNED(SMALL_INT_FAST);
47743 	DUK__DUMPLM_UNSIGNED(SMALL_UINT_FAST);
47744 }
47745 
47746 DUK_LOCAL void duk__dump_misc_options(void) {
47747 	DUK_D(DUK_DPRINT("DUK_VERSION: %ld", (long) DUK_VERSION));
47748 	DUK_D(DUK_DPRINT("DUK_GIT_DESCRIBE: %s", DUK_GIT_DESCRIBE));
47749 	DUK_D(DUK_DPRINT("OS string: %s", DUK_USE_OS_STRING));
47750 	DUK_D(DUK_DPRINT("architecture string: %s", DUK_USE_ARCH_STRING));
47751 	DUK_D(DUK_DPRINT("compiler string: %s", DUK_USE_COMPILER_STRING));
47752 	DUK_D(DUK_DPRINT("debug level: %ld", (long) DUK_USE_DEBUG_LEVEL));
47753 #if defined(DUK_USE_PACKED_TVAL)
47754 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: yes"));
47755 #else
47756 	DUK_D(DUK_DPRINT("DUK_USE_PACKED_TVAL: no"));
47757 #endif
47758 #if defined(DUK_USE_VARIADIC_MACROS)
47759 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: yes"));
47760 #else
47761 	DUK_D(DUK_DPRINT("DUK_USE_VARIADIC_MACROS: no"));
47762 #endif
47763 #if defined(DUK_USE_INTEGER_LE)
47764 	DUK_D(DUK_DPRINT("integer endianness: little"));
47765 #elif defined(DUK_USE_INTEGER_ME)
47766 	DUK_D(DUK_DPRINT("integer endianness: mixed"));
47767 #elif defined(DUK_USE_INTEGER_BE)
47768 	DUK_D(DUK_DPRINT("integer endianness: big"));
47769 #else
47770 	DUK_D(DUK_DPRINT("integer endianness: ???"));
47771 #endif
47772 #if defined(DUK_USE_DOUBLE_LE)
47773 	DUK_D(DUK_DPRINT("IEEE double endianness: little"));
47774 #elif defined(DUK_USE_DOUBLE_ME)
47775 	DUK_D(DUK_DPRINT("IEEE double endianness: mixed"));
47776 #elif defined(DUK_USE_DOUBLE_BE)
47777 	DUK_D(DUK_DPRINT("IEEE double endianness: big"));
47778 #else
47779 	DUK_D(DUK_DPRINT("IEEE double endianness: ???"));
47780 #endif
47781 }
47782 #endif  /* DUK_USE_DEBUG */
47783 
47784 DUK_INTERNAL
47785 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func,
47786                          duk_realloc_function realloc_func,
47787                          duk_free_function free_func,
47788                          void *heap_udata,
47789                          duk_fatal_function fatal_func) {
47790 	duk_heap *res = NULL;
47791 	duk_uint32_t st_initsize;
47792 
47793 	DUK_D(DUK_DPRINT("allocate heap"));
47794 
47795 	/*
47796 	 *  Random config sanity asserts
47797 	 */
47798 
47799 	DUK_ASSERT(DUK_USE_STRTAB_MINSIZE >= 64);
47800 
47801 	DUK_ASSERT((DUK_HTYPE_STRING & 0x01U) == 0);
47802 	DUK_ASSERT((DUK_HTYPE_BUFFER & 0x01U) == 0);
47803 	DUK_ASSERT((DUK_HTYPE_OBJECT & 0x01U) == 1);  /* DUK_HEAPHDR_IS_OBJECT() relies ont his. */
47804 
47805 	/*
47806 	 *  Debug dump type sizes
47807 	 */
47808 
47809 #if defined(DUK_USE_DEBUG)
47810 	duk__dump_misc_options();
47811 	duk__dump_type_sizes();
47812 	duk__dump_type_limits();
47813 #endif
47814 
47815 	/*
47816 	 *  If selftests enabled, run them as early as possible.
47817 	 */
47818 
47819 #if defined(DUK_USE_SELF_TESTS)
47820 	DUK_D(DUK_DPRINT("run self tests"));
47821 	if (duk_selftest_run_tests(alloc_func, realloc_func, free_func, heap_udata) > 0) {
47822 		fatal_func(heap_udata, "self test(s) failed");
47823 	}
47824 	DUK_D(DUK_DPRINT("self tests passed"));
47825 #endif
47826 
47827 	/*
47828 	 *  Important assert-like checks that should be enabled even
47829 	 *  when assertions are otherwise not enabled.
47830 	 */
47831 
47832 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
47833 	/* Can't check sizeof() using preprocessor so explicit check.
47834 	 * This will be optimized away in practice; unfortunately a
47835 	 * warning is generated on some compilers as a result.
47836 	 */
47837 #if defined(DUK_USE_PACKED_TVAL)
47838 	if (sizeof(duk_tval) != 8) {
47839 #else
47840 	if (sizeof(duk_tval) != 16) {
47841 #endif
47842 		fatal_func(heap_udata, "sizeof(duk_tval) not 8 or 16, cannot use DUK_USE_EXEC_REGCONST_OPTIMIZE option");
47843 	}
47844 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
47845 
47846 	/*
47847 	 *  Computed values (e.g. INFINITY)
47848 	 */
47849 
47850 #if defined(DUK_USE_COMPUTED_NAN)
47851 	do {
47852 		/* Workaround for some exotic platforms where NAN is missing
47853 		 * and the expression (0.0 / 0.0) does NOT result in a NaN.
47854 		 * Such platforms use the global 'duk_computed_nan' which must
47855 		 * be initialized at runtime.  Use 'volatile' to ensure that
47856 		 * the compiler will actually do the computation and not try
47857 		 * to do constant folding which might result in the original
47858 		 * problem.
47859 		 */
47860 		volatile double dbl1 = 0.0;
47861 		volatile double dbl2 = 0.0;
47862 		duk_computed_nan = dbl1 / dbl2;
47863 	} while (0);
47864 #endif
47865 
47866 #if defined(DUK_USE_COMPUTED_INFINITY)
47867 	do {
47868 		/* Similar workaround for INFINITY. */
47869 		volatile double dbl1 = 1.0;
47870 		volatile double dbl2 = 0.0;
47871 		duk_computed_infinity = dbl1 / dbl2;
47872 	} while (0);
47873 #endif
47874 
47875 	/*
47876 	 *  Allocate heap struct
47877 	 *
47878 	 *  Use a raw call, all macros expect the heap to be initialized
47879 	 */
47880 
47881 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 1)
47882 	goto failed;
47883 #endif
47884 	DUK_D(DUK_DPRINT("alloc duk_heap object"));
47885 	res = (duk_heap *) alloc_func(heap_udata, sizeof(duk_heap));
47886 	if (!res) {
47887 		goto failed;
47888 	}
47889 
47890 	/*
47891 	 *  Zero the struct, and start initializing roughly in order
47892 	 */
47893 
47894 	duk_memzero(res, sizeof(*res));
47895 #if defined(DUK_USE_ASSERTIONS)
47896 	res->heap_initializing = 1;
47897 #endif
47898 
47899 	/* explicit NULL inits */
47900 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47901 	res->heap_udata = NULL;
47902 	res->heap_allocated = NULL;
47903 #if defined(DUK_USE_REFERENCE_COUNTING)
47904 	res->refzero_list = NULL;
47905 #endif
47906 #if defined(DUK_USE_FINALIZER_SUPPORT)
47907 	res->finalize_list = NULL;
47908 #if defined(DUK_USE_ASSERTIONS)
47909 	res->currently_finalizing = NULL;
47910 #endif
47911 #endif
47912 #if defined(DUK_USE_CACHE_ACTIVATION)
47913 	res->activation_free = NULL;
47914 #endif
47915 #if defined(DUK_USE_CACHE_CATCHER)
47916 	res->catcher_free = NULL;
47917 #endif
47918 	res->heap_thread = NULL;
47919 	res->curr_thread = NULL;
47920 	res->heap_object = NULL;
47921 #if defined(DUK_USE_STRTAB_PTRCOMP)
47922 	res->strtable16 = NULL;
47923 #else
47924 	res->strtable = NULL;
47925 #endif
47926 #if defined(DUK_USE_ROM_STRINGS)
47927 	/* no res->strs[] */
47928 #else  /* DUK_USE_ROM_STRINGS */
47929 #if defined(DUK_USE_HEAPPTR16)
47930 	/* res->strs16[] is zeroed and zero decodes to NULL, so no NULL inits. */
47931 #else
47932 	{
47933 		duk_small_uint_t i;
47934 	        for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
47935 			res->strs[i] = NULL;
47936 	        }
47937 	}
47938 #endif
47939 #endif  /* DUK_USE_ROM_STRINGS */
47940 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47941 	res->dbg_read_cb = NULL;
47942 	res->dbg_write_cb = NULL;
47943 	res->dbg_peek_cb = NULL;
47944 	res->dbg_read_flush_cb = NULL;
47945 	res->dbg_write_flush_cb = NULL;
47946 	res->dbg_request_cb = NULL;
47947 	res->dbg_udata = NULL;
47948 	res->dbg_pause_act = NULL;
47949 #endif
47950 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
47951 
47952 	res->alloc_func = alloc_func;
47953 	res->realloc_func = realloc_func;
47954 	res->free_func = free_func;
47955 	res->heap_udata = heap_udata;
47956 	res->fatal_func = fatal_func;
47957 
47958 	/* XXX: for now there's a pointer packing zero assumption, i.e.
47959 	 * NULL <=> compressed pointer 0.  If this is removed, may need
47960 	 * to precompute e.g. null16 here.
47961 	 */
47962 
47963 	/* res->ms_trigger_counter == 0 -> now causes immediate GC; which is OK */
47964 
47965 	/* Prevent mark-and-sweep and finalizer execution until heap is completely
47966 	 * initialized.
47967 	 */
47968 	DUK_ASSERT(res->ms_prevent_count == 0);
47969 	DUK_ASSERT(res->pf_prevent_count == 0);
47970 	res->ms_prevent_count = 1;
47971 	res->pf_prevent_count = 1;
47972 	DUK_ASSERT(res->ms_running == 0);
47973 
47974 	res->call_recursion_depth = 0;
47975 	res->call_recursion_limit = DUK_USE_NATIVE_CALL_RECLIMIT;
47976 
47977 	/* XXX: use the pointer as a seed for now: mix in time at least */
47978 
47979 	/* The casts through duk_uintptr_t is to avoid the following GCC warning:
47980 	 *
47981 	 *   warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
47982 	 *
47983 	 * This still generates a /Wp64 warning on VS2010 when compiling for x86.
47984 	 */
47985 #if defined(DUK_USE_ROM_STRINGS)
47986 	/* XXX: make a common DUK_USE_ option, and allow custom fixed seed? */
47987 	DUK_D(DUK_DPRINT("using rom strings, force heap hash_seed to fixed value 0x%08lx", (long) DUK__FIXED_HASH_SEED));
47988 	res->hash_seed = (duk_uint32_t) DUK__FIXED_HASH_SEED;
47989 #else  /* DUK_USE_ROM_STRINGS */
47990 	res->hash_seed = (duk_uint32_t) (duk_uintptr_t) res;
47991 #if !defined(DUK_USE_STRHASH_DENSE)
47992 	res->hash_seed ^= 5381;  /* Bernstein hash init value is normally 5381; XOR it in in case pointer low bits are 0 */
47993 #endif
47994 #endif  /* DUK_USE_ROM_STRINGS */
47995 
47996 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
47997 	res->lj.jmpbuf_ptr = NULL;
47998 #endif
47999 	DUK_ASSERT(res->lj.type == DUK_LJ_TYPE_UNKNOWN);  /* zero */
48000 	DUK_ASSERT(res->lj.iserror == 0);
48001 	DUK_TVAL_SET_UNDEFINED(&res->lj.value1);
48002 	DUK_TVAL_SET_UNDEFINED(&res->lj.value2);
48003 
48004 	DUK_ASSERT_LJSTATE_UNSET(res);
48005 
48006 	/*
48007 	 *  Init stringtable: fixed variant
48008 	 */
48009 
48010 	st_initsize = DUK_USE_STRTAB_MINSIZE;
48011 #if defined(DUK_USE_STRTAB_PTRCOMP)
48012 	res->strtable16 = (duk_uint16_t *) alloc_func(heap_udata, sizeof(duk_uint16_t) * st_initsize);
48013 	if (res->strtable16 == NULL) {
48014 		goto failed;
48015 	}
48016 #else
48017 	res->strtable = (duk_hstring **) alloc_func(heap_udata, sizeof(duk_hstring *) * st_initsize);
48018 	if (res->strtable == NULL) {
48019 		goto failed;
48020 	}
48021 #endif
48022 	res->st_size = st_initsize;
48023 	res->st_mask = st_initsize - 1;
48024 #if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
48025 	DUK_ASSERT(res->st_count == 0);
48026 #endif
48027 
48028 #if defined(DUK_USE_STRTAB_PTRCOMP)
48029 	/* zero assumption */
48030 	duk_memzero(res->strtable16, sizeof(duk_uint16_t) * st_initsize);
48031 #else
48032 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48033 	{
48034 		duk_uint32_t i;
48035 	        for (i = 0; i < st_initsize; i++) {
48036 			res->strtable[i] = NULL;
48037 	        }
48038 	}
48039 #else
48040 	duk_memzero(res->strtable, sizeof(duk_hstring *) * st_initsize);
48041 #endif  /* DUK_USE_EXPLICIT_NULL_INIT */
48042 #endif  /* DUK_USE_STRTAB_PTRCOMP */
48043 
48044 	/*
48045 	 *  Init stringcache
48046 	 */
48047 
48048 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48049 	{
48050 		duk_uint_t i;
48051 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
48052 			res->strcache[i].h = NULL;
48053 		}
48054 	}
48055 #endif
48056 
48057 	/*
48058 	 *  Init litcache
48059 	 */
48060 #if defined(DUK_USE_LITCACHE_SIZE)
48061 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
48062 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
48063 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
48064 	{
48065 		duk_uint_t i;
48066 		for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
48067 			res->litcache[i].addr = NULL;
48068 			res->litcache[i].h = NULL;
48069 		}
48070 	}
48071 #endif
48072 #endif  /* DUK_USE_LITCACHE_SIZE */
48073 
48074 	/* XXX: error handling is incomplete.  It would be cleanest if
48075 	 * there was a setjmp catchpoint, so that all init code could
48076 	 * freely throw errors.  If that were the case, the return code
48077 	 * passing here could be removed.
48078 	 */
48079 
48080 	/*
48081 	 *  Init built-in strings
48082 	 */
48083 
48084 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 2)
48085 	goto failed;
48086 #endif
48087 	DUK_D(DUK_DPRINT("heap init: initialize heap strings"));
48088 	if (!duk__init_heap_strings(res)) {
48089 		goto failed;
48090 	}
48091 
48092 	/*
48093 	 *  Init the heap thread
48094 	 */
48095 
48096 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 3)
48097 	goto failed;
48098 #endif
48099 	DUK_D(DUK_DPRINT("heap init: initialize heap thread"));
48100 	if (!duk__init_heap_thread(res)) {
48101 		goto failed;
48102 	}
48103 
48104 	/*
48105 	 *  Init the heap object
48106 	 */
48107 
48108 #if defined(DUK_USE_INJECT_HEAP_ALLOC_ERROR) && (DUK_USE_INJECT_HEAP_ALLOC_ERROR == 4)
48109 	goto failed;
48110 #endif
48111 	DUK_D(DUK_DPRINT("heap init: initialize heap object"));
48112 	DUK_ASSERT(res->heap_thread != NULL);
48113 	res->heap_object = duk_hobject_alloc_unchecked(res, DUK_HOBJECT_FLAG_EXTENSIBLE |
48114 	                                                    DUK_HOBJECT_FLAG_FASTREFS |
48115 	                                                    DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT));
48116 	if (res->heap_object == NULL) {
48117 		goto failed;
48118 	}
48119 	DUK_HOBJECT_INCREF(res->heap_thread, res->heap_object);
48120 
48121 	/*
48122 	 *  Odds and ends depending on the heap thread
48123 	 */
48124 
48125 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
48126 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
48127 	res->rnd_state = (duk_uint32_t) duk_time_get_ecmascript_time(res->heap_thread);
48128 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48129 #else
48130 	res->rnd_state[0] = (duk_uint64_t) duk_time_get_ecmascript_time(res->heap_thread);
48131 	DUK_ASSERT(res->rnd_state[1] == 0);  /* Not filled here, filled in by seed preparation. */
48132 #if 0  /* Manual test values matching misc/xoroshiro128plus_test.c. */
48133 	res->rnd_state[0] = DUK_U64_CONSTANT(0xdeadbeef12345678);
48134 	res->rnd_state[1] = DUK_U64_CONSTANT(0xcafed00d12345678);
48135 #endif
48136 	duk_util_tinyrandom_prepare_seed(res->heap_thread);
48137 	/* Mix in heap pointer: this ensures that if two Duktape heaps are
48138 	 * created on the same millisecond, they get a different PRNG
48139 	 * sequence (unless e.g. virtual memory addresses cause also the
48140 	 * heap object pointer to be the same).
48141 	 */
48142 	{
48143 		duk_uint64_t tmp_u64;
48144 		tmp_u64 = 0;
48145 		duk_memcpy((void *) &tmp_u64,
48146 		           (const void *) &res,
48147 		           (size_t) (sizeof(void *) >= sizeof(duk_uint64_t) ? sizeof(duk_uint64_t) : sizeof(void *)));
48148 		res->rnd_state[1] ^= tmp_u64;
48149 	}
48150 	do {
48151 		duk_small_uint_t i;
48152 		for (i = 0; i < 10; i++) {
48153 			/* Throw away a few initial random numbers just in
48154 			 * case.  Probably unnecessary due to SplitMix64
48155 			 * preparation.
48156 			 */
48157 			(void) duk_util_tinyrandom_get_double(res->heap_thread);
48158 		}
48159 	} while (0);
48160 #endif
48161 #endif
48162 
48163 	/*
48164 	 *  Allow finalizer and mark-and-sweep processing.
48165 	 */
48166 
48167 	DUK_D(DUK_DPRINT("heap init: allow finalizer/mark-and-sweep processing"));
48168 	DUK_ASSERT(res->ms_prevent_count == 1);
48169 	DUK_ASSERT(res->pf_prevent_count == 1);
48170 	res->ms_prevent_count = 0;
48171 	res->pf_prevent_count = 0;
48172 	DUK_ASSERT(res->ms_running == 0);
48173 #if defined(DUK_USE_ASSERTIONS)
48174 	res->heap_initializing = 0;
48175 #endif
48176 
48177 	/*
48178 	 *  All done.
48179 	 */
48180 
48181 	DUK_D(DUK_DPRINT("allocated heap: %p", (void *) res));
48182 	return res;
48183 
48184  failed:
48185 	DUK_D(DUK_DPRINT("heap allocation failed"));
48186 
48187 	if (res != NULL) {
48188 		/* Assumes that allocated pointers and alloc funcs are valid
48189 		 * if res exists.
48190 		 */
48191 		DUK_ASSERT(res->ms_prevent_count == 1);
48192 		DUK_ASSERT(res->pf_prevent_count == 1);
48193 		DUK_ASSERT(res->ms_running == 0);
48194 		if (res->heap_thread != NULL) {
48195 			res->ms_prevent_count = 0;
48196 			res->pf_prevent_count = 0;
48197 		}
48198 #if defined(DUK_USE_ASSERTIONS)
48199 		res->heap_initializing = 0;
48200 #endif
48201 
48202 		DUK_ASSERT(res->alloc_func != NULL);
48203 		DUK_ASSERT(res->realloc_func != NULL);
48204 		DUK_ASSERT(res->free_func != NULL);
48205 		duk_heap_free(res);
48206 	}
48207 
48208 	return NULL;
48209 }
48210 
48211 /* automatic undefs */
48212 #undef DUK__DUMPLM_SIGNED
48213 #undef DUK__DUMPLM_SIGNED_RAW
48214 #undef DUK__DUMPLM_UNSIGNED
48215 #undef DUK__DUMPLM_UNSIGNED_RAW
48216 #undef DUK__DUMPSZ
48217 #undef DUK__FIXED_HASH_SEED
48218 #line 1 "duk_heap_finalize.c"
48219 /*
48220  *  Finalizer handling.
48221  */
48222 
48223 /* #include duk_internal.h -> already included */
48224 
48225 #if defined(DUK_USE_FINALIZER_SUPPORT)
48226 
48227 /*
48228  *  Fake torture finalizer.
48229  */
48230 
48231 #if defined(DUK_USE_FINALIZER_TORTURE)
48232 DUK_LOCAL duk_ret_t duk__fake_global_finalizer(duk_hthread *thr) {
48233 	DUK_DD(DUK_DDPRINT("fake global torture finalizer executed"));
48234 
48235 	/* Require a lot of stack to force a value stack grow/shrink. */
48236 	duk_require_stack(thr, 100000);
48237 
48238 	/* Force a reallocation with pointer change for value stack
48239 	 * to maximize side effects.
48240 	 */
48241 	duk_hthread_valstack_torture_realloc(thr);
48242 
48243 	/* Inner function call, error throw. */
48244 	duk_eval_string_noresult(thr,
48245 		"(function dummy() {\n"
48246 		"    dummy.prototype = null;  /* break reference loop */\n"
48247 		"    try {\n"
48248 		"        throw 'fake-finalizer-dummy-error';\n"
48249 		"    } catch (e) {\n"
48250 		"        void e;\n"
48251 		"    }\n"
48252 		"})()");
48253 
48254 	/* The above creates garbage (e.g. a function instance).  Because
48255 	 * the function/prototype reference loop is broken, it gets collected
48256 	 * immediately by DECREF.  If Function.prototype has a _Finalizer
48257 	 * property (happens in some test cases), the garbage gets queued to
48258 	 * finalize_list.  This still won't cause an infinite loop because
48259 	 * the torture finalizer is called once per finalize_list run and
48260 	 * the garbage gets handled in the same run.  (If the garbage needs
48261 	 * mark-and-sweep collection, an infinite loop might ensue.)
48262 	 */
48263 	return 0;
48264 }
48265 
48266 DUK_LOCAL void duk__run_global_torture_finalizer(duk_hthread *thr) {
48267 	DUK_ASSERT(thr != NULL);
48268 
48269 	/* Avoid fake finalization when callstack limit is near.  Otherwise
48270 	 * a callstack limit error will be created, then refzero'ed.  The
48271 	 * +5 headroom is conservative.
48272 	 */
48273 	if (thr->heap->call_recursion_depth + 5 >= thr->heap->call_recursion_limit ||
48274 	    thr->callstack_top + 5 >= DUK_USE_CALLSTACK_LIMIT) {
48275 		DUK_D(DUK_DPRINT("skip global torture finalizer, too little headroom for call recursion or call stack size"));
48276 		return;
48277 	}
48278 
48279 	/* Run fake finalizer.  Avoid creating unnecessary garbage. */
48280 	duk_push_c_function(thr, duk__fake_global_finalizer, 0 /*nargs*/);
48281 	(void) duk_pcall(thr, 0 /*nargs*/);
48282 	duk_pop(thr);
48283 }
48284 #endif  /* DUK_USE_FINALIZER_TORTURE */
48285 
48286 /*
48287  *  Process the finalize_list to completion.
48288  *
48289  *  An object may be placed on finalize_list by either refcounting or
48290  *  mark-and-sweep.  The refcount of objects placed by refcounting will be
48291  *  zero; the refcount of objects placed by mark-and-sweep is > 0.  In both
48292  *  cases the refcount is bumped by 1 artificially so that a REFZERO event
48293  *  can never happen while an object is waiting for finalization.  Without
48294  *  this bump a REFZERO could now happen because user code may call
48295  *  duk_push_heapptr() and then pop a value even when it's on finalize_list.
48296  *
48297  *  List processing assumes refcounts are kept up-to-date at all times, so
48298  *  that once the finalizer returns, a zero refcount is a reliable reason to
48299  *  free the object immediately rather than place it back to the heap.  This
48300  *  is the case because we run outside of refzero_list processing so that
48301  *  DECREF cascades are handled fully inline.
48302  *
48303  *  For mark-and-sweep queued objects (had_zero_refcount false) the object
48304  *  may be freed immediately if its refcount is zero after the finalizer call
48305  *  (i.e. finalizer removed the reference loop for the object).  If not, the
48306  *  next mark-and-sweep will collect the object unless it has become reachable
48307  *  (i.e. rescued) by that time and its refcount hasn't fallen to zero before
48308  *  that.  Mark-and-sweep detects these objects because their FINALIZED flag
48309  *  is set.
48310  *
48311  *  There's an inherent limitation for mark-and-sweep finalizer rescuing: an
48312  *  object won't get refinalized if (1) it's rescued, but (2) becomes
48313  *  unreachable before mark-and-sweep has had time to notice it.  The next
48314  *  mark-and-sweep round simply doesn't have any information of whether the
48315  *  object has been unreachable the whole time or not (the only way to get
48316  *  that information would be a mark-and-sweep pass for *every finalized
48317  *  object*).  This is awkward for the application because the mark-and-sweep
48318  *  round is not generally visible or under full application control.
48319  *
48320  *  For refcount queued objects (had_zero_refcount true) the object is either
48321  *  immediately freed or rescued, and waiting for a mark-and-sweep round is not
48322  *  necessary (or desirable); FINALIZED is cleared when a rescued object is
48323  *  queued back to heap_allocated.  The object is eligible for finalization
48324  *  again (either via refcounting or mark-and-sweep) immediately after being
48325  *  rescued.  If a refcount finalized object is placed into an unreachable
48326  *  reference loop by its finalizer, it will get collected by mark-and-sweep
48327  *  and currently the finalizer will execute again.
48328  *
48329  *  There's a special case where:
48330  *
48331  *    - Mark-and-sweep queues an object to finalize_list for finalization.
48332  *    - The finalizer is executed, FINALIZED is set, and object is queued
48333  *      back to heap_allocated, waiting for a new mark-and-sweep round.
48334  *    - The object's refcount drops to zero before mark-and-sweep has a
48335  *      chance to run another round and make a rescue/free decision.
48336  *
48337  *  This is now handled by refzero code: if an object has a finalizer but
48338  *  FINALIZED is already set, the object is freed without finalizer processing.
48339  *  The outcome is the same as if mark-and-sweep was executed at that point;
48340  *  mark-and-sweep would also free the object without another finalizer run.
48341  *  This could also be changed so that the refzero-triggered finalizer *IS*
48342  *  executed: being refzero collected implies someone has operated on the
48343  *  object so it hasn't been totally unreachable the whole time.  This would
48344  *  risk a finalizer loop however.
48345  */
48346 
48347 DUK_INTERNAL void duk_heap_process_finalize_list(duk_heap *heap) {
48348 	duk_heaphdr *curr;
48349 #if defined(DUK_USE_DEBUG)
48350 	duk_size_t count = 0;
48351 #endif
48352 
48353 	DUK_DDD(DUK_DDDPRINT("duk_heap_process_finalize_list: %p", (void *) heap));
48354 
48355 	if (heap->pf_prevent_count != 0) {
48356 		DUK_DDD(DUK_DDDPRINT("skip finalize_list processing: pf_prevent_count != 0"));
48357 		return;
48358 	}
48359 
48360 	/* Heap alloc prevents mark-and-sweep before heap_thread is ready. */
48361 	DUK_ASSERT(heap != NULL);
48362 	DUK_ASSERT(heap->heap_thread != NULL);
48363 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
48364 #if defined(DUK_USE_REFERENCE_COUNTING)
48365 	DUK_ASSERT(heap->refzero_list == NULL);
48366 #endif
48367 
48368 	DUK_ASSERT(heap->pf_prevent_count == 0);
48369 	heap->pf_prevent_count = 1;
48370 
48371 	/* Mark-and-sweep no longer needs to be prevented when running
48372 	 * finalizers: mark-and-sweep skips any rescue decisions if there
48373 	 * are any objects in finalize_list when mark-and-sweep is entered.
48374 	 * This protects finalized objects from incorrect rescue decisions
48375 	 * caused by finalize_list being a reachability root and only
48376 	 * partially processed.  Freeing decisions are not postponed.
48377 	 */
48378 
48379 	/* When finalizer torture is enabled, make a fake finalizer call with
48380 	 * maximum side effects regardless of whether finalize_list is empty.
48381 	 */
48382 #if defined(DUK_USE_FINALIZER_TORTURE)
48383 	duk__run_global_torture_finalizer(heap->heap_thread);
48384 #endif
48385 
48386 	/* Process finalize_list until it becomes empty.  There's currently no
48387 	 * protection against a finalizer always creating more garbage.
48388 	 */
48389 	while ((curr = heap->finalize_list) != NULL) {
48390 #if defined(DUK_USE_REFERENCE_COUNTING)
48391 		duk_bool_t queue_back;
48392 #endif
48393 
48394 		DUK_DD(DUK_DDPRINT("processing finalize_list entry: %p -> %!iO", (void *) curr, curr));
48395 
48396 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* Only objects have finalizers. */
48397 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
48398 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(curr));
48399 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(curr));  /* All objects on finalize_list will have this flag (except object being finalized right now). */
48400 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));   /* Queueing code ensures. */
48401 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* ROM objects never get freed (or finalized). */
48402 
48403 #if defined(DUK_USE_ASSERTIONS)
48404 		DUK_ASSERT(heap->currently_finalizing == NULL);
48405 		heap->currently_finalizing = curr;
48406 #endif
48407 
48408 		/* Clear FINALIZABLE for object being finalized, so that
48409 		 * duk_push_heapptr() can properly ignore the object.
48410 		 */
48411 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48412 
48413 		if (DUK_LIKELY(!heap->pf_skip_finalizers)) {
48414 			/* Run the finalizer, duk_heap_run_finalizer() sets
48415 			 * and checks for FINALIZED to prevent the finalizer
48416 			 * from executing multiple times per finalization cycle.
48417 			 * (This safeguard shouldn't be actually needed anymore).
48418 			 */
48419 
48420 #if defined(DUK_USE_REFERENCE_COUNTING)
48421 			duk_bool_t had_zero_refcount;
48422 #endif
48423 
48424 			/* The object's refcount is >0 throughout so it won't be
48425 			 * refzero processed prematurely.
48426 			 */
48427 #if defined(DUK_USE_REFERENCE_COUNTING)
48428 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48429 			had_zero_refcount = (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1);  /* Preincremented on finalize_list insert. */
48430 #endif
48431 
48432 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48433 			duk_heap_run_finalizer(heap, (duk_hobject *) curr);  /* must never longjmp */
48434 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
48435 			/* XXX: assert that object is still in finalize_list
48436 			 * when duk_push_heapptr() allows automatic rescue.
48437 			 */
48438 
48439 #if defined(DUK_USE_REFERENCE_COUNTING)
48440 			DUK_DD(DUK_DDPRINT("refcount after finalizer (includes bump): %ld", (long) DUK_HEAPHDR_GET_REFCOUNT(curr)));
48441 			if (DUK_HEAPHDR_GET_REFCOUNT(curr) == 1) {  /* Only artificial bump in refcount? */
48442 #if defined(DUK_USE_DEBUG)
48443 				if (had_zero_refcount) {
48444 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (refcount queued)"));
48445 				} else {
48446 					DUK_DD(DUK_DDPRINT("finalized object's refcount is zero -> free immediately (mark-and-sweep queued)"));
48447 				}
48448 #endif
48449 				queue_back = 0;
48450 			} else
48451 #endif
48452 			{
48453 #if defined(DUK_USE_REFERENCE_COUNTING)
48454 				queue_back = 1;
48455 				if (had_zero_refcount) {
48456 					/* When finalization is triggered
48457 					 * by refzero and we queue the object
48458 					 * back, clear FINALIZED right away
48459 					 * so that the object can be refinalized
48460 					 * immediately if necessary.
48461 					 */
48462 					DUK_HEAPHDR_CLEAR_FINALIZED(curr);
48463 				}
48464 #endif
48465 			}
48466 		} else {
48467 			/* Used during heap destruction: don't actually run finalizers
48468 			 * because we're heading into forced finalization.  Instead,
48469 			 * queue finalizable objects back to the heap_allocated list.
48470 			 */
48471 			DUK_D(DUK_DPRINT("skip finalizers flag set, queue object to heap_allocated without finalizing"));
48472 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
48473 #if defined(DUK_USE_REFERENCE_COUNTING)
48474 			queue_back = 1;
48475 #endif
48476 		}
48477 
48478 		/* Dequeue object from finalize_list.  Note that 'curr' may no
48479 		 * longer be finalize_list head because new objects may have
48480 		 * been queued to the list.  As a result we can't optimize for
48481 		 * the single-linked heap case and must scan the list for
48482 		 * removal, typically the scan is very short however.
48483 		 */
48484 		DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap, curr);
48485 
48486 		/* Queue back to heap_allocated or free immediately. */
48487 #if defined(DUK_USE_REFERENCE_COUNTING)
48488 		if (queue_back) {
48489 			/* FINALIZED is only cleared if object originally
48490 			 * queued for finalization by refcounting.  For
48491 			 * mark-and-sweep FINALIZED is left set, so that
48492 			 * next mark-and-sweep round can make a rescue/free
48493 			 * decision.
48494 			 */
48495 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) >= 1);
48496 			DUK_HEAPHDR_PREDEC_REFCOUNT(curr);  /* Remove artificial refcount bump. */
48497 			DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48498 			DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48499 		} else {
48500 			/* No need to remove the refcount bump here. */
48501 			DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
48502 			DUK_DD(DUK_DDPRINT("refcount finalize after finalizer call: %!O", curr));
48503 			duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
48504 			duk_free_hobject(heap, (duk_hobject *) curr);
48505 			DUK_DD(DUK_DDPRINT("freed hobject after finalization: %p", (void *) curr));
48506 		}
48507 #else  /* DUK_USE_REFERENCE_COUNTING */
48508 		DUK_HEAPHDR_CLEAR_FINALIZABLE(curr);
48509 		DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, curr);
48510 #endif  /* DUK_USE_REFERENCE_COUNTING */
48511 
48512 #if defined(DUK_USE_DEBUG)
48513 		count++;
48514 #endif
48515 
48516 #if defined(DUK_USE_ASSERTIONS)
48517 		DUK_ASSERT(heap->currently_finalizing != NULL);
48518 		heap->currently_finalizing = NULL;
48519 #endif
48520 	}
48521 
48522 	/* finalize_list will always be processed completely. */
48523 	DUK_ASSERT(heap->finalize_list == NULL);
48524 
48525 #if 0
48526 	/* While NORZ macros are used above, this is unnecessary because the
48527 	 * only pending side effects are now finalizers, and finalize_list is
48528 	 * empty.
48529 	 */
48530 	DUK_REFZERO_CHECK_SLOW(heap->heap_thread);
48531 #endif
48532 
48533 	/* Prevent count may be bumped while finalizers run, but should always
48534 	 * be reliably unbumped by the time we get here.
48535 	 */
48536 	DUK_ASSERT(heap->pf_prevent_count == 1);
48537 	heap->pf_prevent_count = 0;
48538 
48539 #if defined(DUK_USE_DEBUG)
48540 	DUK_DD(DUK_DDPRINT("duk_heap_process_finalize_list: %ld finalizers called", (long) count));
48541 #endif
48542 }
48543 
48544 /*
48545  *  Run an duk_hobject finalizer.  Must never throw an uncaught error
48546  *  (but may throw caught errors).
48547  *
48548  *  There is no return value.  Any return value or error thrown by
48549  *  the finalizer is ignored (although errors are debug logged).
48550  *
48551  *  Notes:
48552  *
48553  *    - The finalizer thread 'top' assertions are there because it is
48554  *      critical that strict stack policy is observed (i.e. no cruft
48555  *      left on the finalizer stack).
48556  */
48557 
48558 DUK_LOCAL duk_ret_t duk__finalize_helper(duk_hthread *thr, void *udata) {
48559 	DUK_ASSERT(thr != NULL);
48560 	DUK_UNREF(udata);
48561 
48562 	DUK_DDD(DUK_DDDPRINT("protected finalization helper running"));
48563 
48564 	/* [... obj] */
48565 
48566 	/* _Finalizer property is read without checking if the value is
48567 	 * callable or even exists.  This is intentional, and handled
48568 	 * by throwing an error which is caught by the safe call wrapper.
48569 	 *
48570 	 * XXX: Finalizer lookup should traverse the prototype chain (to allow
48571 	 * inherited finalizers) but should not invoke accessors or proxy object
48572 	 * behavior.  At the moment this lookup will invoke proxy behavior, so
48573 	 * caller must ensure that this function is not called if the target is
48574 	 * a Proxy.
48575 	 */
48576 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FINALIZER);  /* -> [... obj finalizer] */
48577 	duk_dup_m2(thr);
48578 	duk_push_boolean(thr, DUK_HEAP_HAS_FINALIZER_NORESCUE(thr->heap));
48579 	DUK_DDD(DUK_DDDPRINT("calling finalizer"));
48580 	duk_call(thr, 2);  /* [ ... obj finalizer obj heapDestruct ]  -> [ ... obj retval ] */
48581 	DUK_DDD(DUK_DDDPRINT("finalizer returned successfully"));
48582 	return 0;
48583 
48584 	/* Note: we rely on duk_safe_call() to fix up the stack for the caller,
48585 	 * so we don't need to pop stuff here.  There is no return value;
48586 	 * caller determines rescued status based on object refcount.
48587 	 */
48588 }
48589 
48590 DUK_INTERNAL void duk_heap_run_finalizer(duk_heap *heap, duk_hobject *obj) {
48591 	duk_hthread *thr;
48592 	duk_ret_t rc;
48593 #if defined(DUK_USE_ASSERTIONS)
48594 	duk_idx_t entry_top;
48595 #endif
48596 
48597 	DUK_DD(DUK_DDPRINT("running duk_hobject finalizer for object: %p", (void *) obj));
48598 
48599 	DUK_ASSERT(heap != NULL);
48600 	DUK_ASSERT(heap->heap_thread != NULL);
48601 	thr = heap->heap_thread;
48602 	DUK_ASSERT(obj != NULL);
48603 	DUK_ASSERT_VALSTACK_SPACE(heap->heap_thread, 1);
48604 
48605 #if defined(DUK_USE_ASSERTIONS)
48606 	entry_top = duk_get_top(thr);
48607 #endif
48608 	/*
48609 	 *  Get and call the finalizer.  All of this must be wrapped
48610 	 *  in a protected call, because even getting the finalizer
48611 	 *  may trigger an error (getter may throw one, for instance).
48612 	 */
48613 
48614 	/* ROM objects could inherit a finalizer, but they are never deemed
48615 	 * unreachable by mark-and-sweep, and their refcount never falls to 0.
48616 	 */
48617 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
48618 
48619 	/* Duktape 2.1: finalize_list never contains objects with FINALIZED
48620 	 * set, so no need to check here.
48621 	 */
48622 	DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj));
48623 #if 0
48624 	if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) obj)) {
48625 		DUK_D(DUK_DPRINT("object already finalized, avoid running finalizer twice: %!O", obj));
48626 		return;
48627 	}
48628 #endif
48629 	DUK_HEAPHDR_SET_FINALIZED((duk_heaphdr *) obj);  /* ensure never re-entered until rescue cycle complete */
48630 
48631 #if defined(DUK_USE_ES6_PROXY)
48632 	if (DUK_HOBJECT_IS_PROXY(obj)) {
48633 		/* This may happen if duk_set_finalizer() or Duktape.fin() is
48634 		 * called for a Proxy object.  In such cases the fast finalizer
48635 		 * flag will be set on the Proxy, not the target, and neither
48636 		 * will be finalized.
48637 		 */
48638 		DUK_D(DUK_DPRINT("object is a Proxy, skip finalizer call"));
48639 		return;
48640 	}
48641 #endif  /* DUK_USE_ES6_PROXY */
48642 
48643 	duk_push_hobject(thr, obj);  /* this also increases refcount by one */
48644 	rc = duk_safe_call(thr, duk__finalize_helper, NULL /*udata*/, 0 /*nargs*/, 1 /*nrets*/);  /* -> [... obj retval/error] */
48645 	DUK_ASSERT_TOP(thr, entry_top + 2);  /* duk_safe_call discipline */
48646 
48647 	if (rc != DUK_EXEC_SUCCESS) {
48648 		/* Note: we ask for one return value from duk_safe_call to get this
48649 		 * error debugging here.
48650 		 */
48651 		DUK_D(DUK_DPRINT("wrapped finalizer call failed for object %p (ignored); error: %!T",
48652 		                 (void *) obj, (duk_tval *) duk_get_tval(thr, -1)));
48653 	}
48654 	duk_pop_2(thr);  /* -> [...] */
48655 
48656 	DUK_ASSERT_TOP(thr, entry_top);
48657 }
48658 
48659 #else  /* DUK_USE_FINALIZER_SUPPORT */
48660 
48661 /* nothing */
48662 
48663 #endif  /* DUK_USE_FINALIZER_SUPPORT */
48664 #line 1 "duk_heap_hashstring.c"
48665 /*
48666  *  String hash computation (interning).
48667  *
48668  *  String hashing is performance critical because a string hash is computed
48669  *  for all new strings which are candidates to be added to the string table.
48670  *  However, strings actually added to the string table go through a codepoint
48671  *  length calculation which dominates performance because it goes through
48672  *  every byte of the input string (but only for strings added).
48673  *
48674  *  The string hash algorithm should be fast, but on the other hand provide
48675  *  good enough hashes to ensure both string table and object property table
48676  *  hash tables work reasonably well (i.e., there aren't too many collisions
48677  *  with real world inputs).  Unless the hash is cryptographic, it's always
48678  *  possible to craft inputs with maximal hash collisions.
48679  *
48680  *  NOTE: The hash algorithms must match tools/dukutil.py:duk_heap_hashstring()
48681  *  for ROM string support!
48682  */
48683 
48684 /* #include duk_internal.h -> already included */
48685 
48686 #if defined(DUK_USE_STRHASH_DENSE)
48687 /* Constants for duk_hashstring(). */
48688 #define DUK__STRHASH_SHORTSTRING   4096L
48689 #define DUK__STRHASH_MEDIUMSTRING  (256L * 1024L)
48690 #define DUK__STRHASH_BLOCKSIZE     256L
48691 
48692 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48693 	duk_uint32_t hash;
48694 
48695 	/* Use Murmurhash2 directly for short strings, and use "block skipping"
48696 	 * for long strings: hash an initial part and then sample the rest of
48697 	 * the string with reasonably sized chunks.  An initial offset for the
48698 	 * sampling is computed based on a hash of the initial part of the string;
48699 	 * this is done to (usually) avoid the case where all long strings have
48700 	 * certain offset ranges which are never sampled.
48701 	 *
48702 	 * Skip should depend on length and bound the total time to roughly
48703 	 * logarithmic.  With current values:
48704 	 *
48705 	 *   1M string => 256 * 241 = 61696 bytes (0.06M) of hashing
48706 	 *   1G string => 256 * 16321 = 4178176 bytes (3.98M) of hashing
48707 	 *
48708 	 * XXX: It would be better to compute the skip offset more "smoothly"
48709 	 * instead of having a few boundary values.
48710 	 */
48711 
48712 	/* note: mixing len into seed improves hashing when skipping */
48713 	duk_uint32_t str_seed = heap->hash_seed ^ ((duk_uint32_t) len);
48714 
48715 	if (len <= DUK__STRHASH_SHORTSTRING) {
48716 		hash = duk_util_hashbytes(str, len, str_seed);
48717 	} else {
48718 		duk_size_t off;
48719 		duk_size_t skip;
48720 
48721 		if (len <= DUK__STRHASH_MEDIUMSTRING) {
48722 			skip = (duk_size_t) (16 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48723 		} else {
48724 			skip = (duk_size_t) (256 * DUK__STRHASH_BLOCKSIZE + DUK__STRHASH_BLOCKSIZE);
48725 		}
48726 
48727 		hash = duk_util_hashbytes(str, (duk_size_t) DUK__STRHASH_SHORTSTRING, str_seed);
48728 		off = DUK__STRHASH_SHORTSTRING + (skip * (hash % 256)) / 256;
48729 
48730 		/* XXX: inefficient loop */
48731 		while (off < len) {
48732 			duk_size_t left = len - off;
48733 			duk_size_t now = (duk_size_t) (left > DUK__STRHASH_BLOCKSIZE ? DUK__STRHASH_BLOCKSIZE : left);
48734 			hash ^= duk_util_hashbytes(str + off, now, str_seed);
48735 			off += skip;
48736 		}
48737 	}
48738 
48739 #if defined(DUK_USE_STRHASH16)
48740 	/* Truncate to 16 bits here, so that a computed hash can be compared
48741 	 * against a hash stored in a 16-bit field.
48742 	 */
48743 	hash &= 0x0000ffffUL;
48744 #endif
48745 	return hash;
48746 }
48747 #else  /* DUK_USE_STRHASH_DENSE */
48748 DUK_INTERNAL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len) {
48749 	duk_uint32_t hash;
48750 	duk_size_t step;
48751 	duk_size_t off;
48752 
48753 	/* Slightly modified "Bernstein hash" from:
48754 	 *
48755 	 *     http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
48756 	 *
48757 	 * Modifications: string skipping and reverse direction similar to
48758 	 * Lua 5.1.5, and different hash initializer.
48759 	 *
48760 	 * The reverse direction ensures last byte it always included in the
48761 	 * hash which is a good default as changing parts of the string are
48762 	 * more often in the suffix than in the prefix.
48763 	 */
48764 
48765 	hash = heap->hash_seed ^ ((duk_uint32_t) len);  /* Bernstein hash init value is normally 5381 */
48766 	step = (len >> DUK_USE_STRHASH_SKIP_SHIFT) + 1;
48767 	for (off = len; off >= step; off -= step) {
48768 		DUK_ASSERT(off >= 1);  /* off >= step, and step >= 1 */
48769 		hash = (hash * 33) + str[off - 1];
48770 	}
48771 
48772 #if defined(DUK_USE_STRHASH16)
48773 	/* Truncate to 16 bits here, so that a computed hash can be compared
48774 	 * against a hash stored in a 16-bit field.
48775 	 */
48776 	hash &= 0x0000ffffUL;
48777 #endif
48778 	return hash;
48779 }
48780 #endif  /* DUK_USE_STRHASH_DENSE */
48781 
48782 /* automatic undefs */
48783 #undef DUK__STRHASH_BLOCKSIZE
48784 #undef DUK__STRHASH_MEDIUMSTRING
48785 #undef DUK__STRHASH_SHORTSTRING
48786 #line 1 "duk_heap_markandsweep.c"
48787 /*
48788  *  Mark-and-sweep garbage collection.
48789  */
48790 
48791 /* #include duk_internal.h -> already included */
48792 
48793 DUK_LOCAL_DECL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h);
48794 DUK_LOCAL_DECL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h);
48795 DUK_LOCAL_DECL void duk__mark_tval(duk_heap *heap, duk_tval *tv);
48796 DUK_LOCAL_DECL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count);
48797 
48798 /*
48799  *  Marking functions for heap types: mark children recursively.
48800  */
48801 
48802 DUK_LOCAL void duk__mark_hstring(duk_heap *heap, duk_hstring *h) {
48803 	DUK_UNREF(heap);
48804 	DUK_UNREF(h);
48805 
48806 	DUK_DDD(DUK_DDDPRINT("duk__mark_hstring: %p", (void *) h));
48807 	DUK_ASSERT(h);
48808 
48809 	/* nothing to process */
48810 }
48811 
48812 DUK_LOCAL void duk__mark_hobject(duk_heap *heap, duk_hobject *h) {
48813 	duk_uint_fast32_t i;
48814 
48815 	DUK_DDD(DUK_DDDPRINT("duk__mark_hobject: %p", (void *) h));
48816 
48817 	DUK_ASSERT(h);
48818 
48819 	/* XXX: use advancing pointers instead of index macros -> faster and smaller? */
48820 
48821 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(h); i++) {
48822 		duk_hstring *key = DUK_HOBJECT_E_GET_KEY(heap, h, i);
48823 		if (key == NULL) {
48824 			continue;
48825 		}
48826 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) key);
48827 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, h, i)) {
48828 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.get);
48829 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->a.set);
48830 		} else {
48831 			duk__mark_tval(heap, &DUK_HOBJECT_E_GET_VALUE_PTR(heap, h, i)->v);
48832 		}
48833 	}
48834 
48835 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(h); i++) {
48836 		duk__mark_tval(heap, DUK_HOBJECT_A_GET_VALUE_PTR(heap, h, i));
48837 	}
48838 
48839 	/* Hash part is a 'weak reference' and does not contribute. */
48840 
48841 	duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HOBJECT_GET_PROTOTYPE(heap, h));
48842 
48843 	/* Fast path for objects which don't have a subclass struct, or have a
48844 	 * subclass struct but nothing that needs marking in the subclass struct.
48845 	 */
48846 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
48847 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
48848 		return;
48849 	}
48850 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
48851 
48852 	/* XXX: reorg, more common first */
48853 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
48854 		duk_hcompfunc *f = (duk_hcompfunc *) h;
48855 		duk_tval *tv, *tv_end;
48856 		duk_hobject **fn, **fn_end;
48857 
48858 		DUK_ASSERT_HCOMPFUNC_VALID(f);
48859 
48860 		/* 'data' is reachable through every compiled function which
48861 		 * contains a reference.
48862 		 */
48863 
48864 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_DATA(heap, f));
48865 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
48866 		duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
48867 
48868 		if (DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL) {
48869 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
48870 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
48871 			while (tv < tv_end) {
48872 				duk__mark_tval(heap, tv);
48873 				tv++;
48874 			}
48875 
48876 			fn = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
48877 			fn_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
48878 			while (fn < fn_end) {
48879 				duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) *fn);
48880 				fn++;
48881 			}
48882 		} else {
48883 			/* May happen in some out-of-memory corner cases. */
48884 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping marking"));
48885 		}
48886 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
48887 		duk_hdecenv *e = (duk_hdecenv *) h;
48888 		DUK_ASSERT_HDECENV_VALID(e);
48889 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->thread);
48890 		duk__mark_heaphdr(heap, (duk_heaphdr *) e->varmap);
48891 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
48892 		duk_hobjenv *e = (duk_hobjenv *) h;
48893 		DUK_ASSERT_HOBJENV_VALID(e);
48894 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) e->target);
48895 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
48896 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
48897 		duk_hbufobj *b = (duk_hbufobj *) h;
48898 		DUK_ASSERT_HBUFOBJ_VALID(b);
48899 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf);
48900 		duk__mark_heaphdr(heap, (duk_heaphdr *) b->buf_prop);
48901 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
48902 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
48903 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
48904 		DUK_ASSERT_HBOUNDFUNC_VALID(f);
48905 		duk__mark_tval(heap, &f->target);
48906 		duk__mark_tval(heap, &f->this_binding);
48907 		duk__mark_tvals(heap, f->args, f->nargs);
48908 #if defined(DUK_USE_ES6_PROXY)
48909 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
48910 		duk_hproxy *p = (duk_hproxy *) h;
48911 		DUK_ASSERT_HPROXY_VALID(p);
48912 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->target);
48913 		duk__mark_heaphdr_nonnull(heap, (duk_heaphdr *) p->handler);
48914 #endif  /* DUK_USE_ES6_PROXY */
48915 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
48916 		duk_hthread *t = (duk_hthread *) h;
48917 		duk_activation *act;
48918 		duk_tval *tv;
48919 
48920 		DUK_ASSERT_HTHREAD_VALID(t);
48921 
48922 		tv = t->valstack;
48923 		while (tv < t->valstack_top) {
48924 			duk__mark_tval(heap, tv);
48925 			tv++;
48926 		}
48927 
48928 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
48929 			duk__mark_heaphdr(heap, (duk_heaphdr *) DUK_ACT_GET_FUNC(act));
48930 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->var_env);
48931 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->lex_env);
48932 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
48933 			duk__mark_heaphdr(heap, (duk_heaphdr *) act->prev_caller);
48934 #endif
48935 #if 0  /* nothing now */
48936 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
48937 			}
48938 #endif
48939 		}
48940 
48941 		duk__mark_heaphdr(heap, (duk_heaphdr *) t->resumer);
48942 
48943 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
48944 			duk__mark_heaphdr(heap, (duk_heaphdr *) t->builtins[i]);
48945 		}
48946 	} else {
48947 		/* We may come here if the object should have a FASTREFS flag
48948 		 * but it's missing for some reason.  Assert for never getting
48949 		 * here; however, other than performance, this is harmless.
48950 		 */
48951 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
48952 		DUK_ASSERT(0);
48953 	}
48954 }
48955 
48956 /* Mark any duk_heaphdr type.  Recursion tracking happens only here. */
48957 DUK_LOCAL void duk__mark_heaphdr(duk_heap *heap, duk_heaphdr *h) {
48958 	DUK_DDD(DUK_DDDPRINT("duk__mark_heaphdr %p, type %ld",
48959 	                     (void *) h,
48960 	                     (h != NULL ? (long) DUK_HEAPHDR_GET_TYPE(h) : (long) -1)));
48961 
48962 	/* XXX: add non-null variant? */
48963 	if (h == NULL) {
48964 		return;
48965 	}
48966 
48967 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h) || DUK_HEAPHDR_HAS_REACHABLE(h));
48968 
48969 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
48970 	if (!DUK_HEAPHDR_HAS_READONLY(h)) {
48971 		h->h_assert_refcount++;  /* Comparison refcount: bump even if already reachable. */
48972 	}
48973 #endif
48974 	if (DUK_HEAPHDR_HAS_REACHABLE(h)) {
48975 		DUK_DDD(DUK_DDDPRINT("already marked reachable, skip"));
48976 		return;
48977 	}
48978 #if defined(DUK_USE_ROM_OBJECTS)
48979 	/* READONLY objects always have REACHABLE set, so the check above
48980 	 * will prevent READONLY objects from being marked here.
48981 	 */
48982 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(h));
48983 #endif
48984 
48985 	DUK_HEAPHDR_SET_REACHABLE(h);
48986 
48987 	if (heap->ms_recursion_depth >= DUK_USE_MARK_AND_SWEEP_RECLIMIT) {
48988 		DUK_D(DUK_DPRINT("mark-and-sweep recursion limit reached, marking as temproot: %p", (void *) h));
48989 		DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap);
48990 		DUK_HEAPHDR_SET_TEMPROOT(h);
48991 		return;
48992 	}
48993 
48994 	heap->ms_recursion_depth++;
48995 	DUK_ASSERT(heap->ms_recursion_depth != 0);  /* Wrap. */
48996 
48997 	switch (DUK_HEAPHDR_GET_TYPE(h)) {
48998 	case DUK_HTYPE_STRING:
48999 		duk__mark_hstring(heap, (duk_hstring *) h);
49000 		break;
49001 	case DUK_HTYPE_OBJECT:
49002 		duk__mark_hobject(heap, (duk_hobject *) h);
49003 		break;
49004 	case DUK_HTYPE_BUFFER:
49005 		/* nothing to mark */
49006 		break;
49007 	default:
49008 		DUK_D(DUK_DPRINT("attempt to mark heaphdr %p with invalid htype %ld", (void *) h, (long) DUK_HEAPHDR_GET_TYPE(h)));
49009 		DUK_UNREACHABLE();
49010 	}
49011 
49012 	DUK_ASSERT(heap->ms_recursion_depth > 0);
49013 	heap->ms_recursion_depth--;
49014 }
49015 
49016 DUK_LOCAL void duk__mark_tval(duk_heap *heap, duk_tval *tv) {
49017 	DUK_DDD(DUK_DDDPRINT("duk__mark_tval %p", (void *) tv));
49018 	if (tv == NULL) {
49019 		return;
49020 	}
49021 	if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49022 		duk_heaphdr *h;
49023 		h = DUK_TVAL_GET_HEAPHDR(tv);
49024 		DUK_ASSERT(h != NULL);
49025 		duk__mark_heaphdr_nonnull(heap, h);
49026 	}
49027 }
49028 
49029 DUK_LOCAL void duk__mark_tvals(duk_heap *heap, duk_tval *tv, duk_idx_t count) {
49030 	DUK_ASSERT(count == 0 || tv != NULL);
49031 
49032 	while (count-- > 0) {
49033 		if (DUK_TVAL_IS_HEAP_ALLOCATED(tv)) {
49034 			duk_heaphdr *h;
49035 			h = DUK_TVAL_GET_HEAPHDR(tv);
49036 			DUK_ASSERT(h != NULL);
49037 			duk__mark_heaphdr_nonnull(heap, h);
49038 		}
49039 		tv++;
49040 	}
49041 }
49042 
49043 /* Mark any duk_heaphdr type, caller guarantees a non-NULL pointer. */
49044 DUK_LOCAL void duk__mark_heaphdr_nonnull(duk_heap *heap, duk_heaphdr *h) {
49045 	/* For now, just call the generic handler.  Change when call sites
49046 	 * are changed too.
49047 	 */
49048 	duk__mark_heaphdr(heap, h);
49049 }
49050 
49051 /*
49052  *  Mark the heap.
49053  */
49054 
49055 DUK_LOCAL void duk__mark_roots_heap(duk_heap *heap) {
49056 	duk_small_uint_t i;
49057 
49058 	DUK_DD(DUK_DDPRINT("duk__mark_roots_heap: %p", (void *) heap));
49059 
49060 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_thread);
49061 	duk__mark_heaphdr(heap, (duk_heaphdr *) heap->heap_object);
49062 
49063 	for (i = 0; i < DUK_HEAP_NUM_STRINGS; i++) {
49064 		duk_hstring *h = DUK_HEAP_GET_STRING(heap, i);
49065 		duk__mark_heaphdr(heap, (duk_heaphdr *) h);
49066 	}
49067 
49068 	duk__mark_tval(heap, &heap->lj.value1);
49069 	duk__mark_tval(heap, &heap->lj.value2);
49070 
49071 #if defined(DUK_USE_DEBUGGER_SUPPORT)
49072 	for (i = 0; i < heap->dbg_breakpoint_count; i++) {
49073 		duk__mark_heaphdr(heap, (duk_heaphdr *) heap->dbg_breakpoints[i].filename);
49074 	}
49075 #endif
49076 }
49077 
49078 /*
49079  *  Mark unreachable, finalizable objects.
49080  *
49081  *  Such objects will be moved aside and their finalizers run later.  They
49082  *  have to be treated as reachability roots for their properties etc to
49083  *  remain allocated.  This marking is only done for unreachable values which
49084  *  would be swept later.
49085  *
49086  *  Objects are first marked FINALIZABLE and only then marked as reachability
49087  *  roots; otherwise circular references might be handled inconsistently.
49088  */
49089 
49090 #if defined(DUK_USE_FINALIZER_SUPPORT)
49091 DUK_LOCAL void duk__mark_finalizable(duk_heap *heap) {
49092 	duk_heaphdr *hdr;
49093 	duk_size_t count_finalizable = 0;
49094 
49095 	DUK_DD(DUK_DDPRINT("duk__mark_finalizable: %p", (void *) heap));
49096 
49097 	DUK_ASSERT(heap->heap_thread != NULL);
49098 
49099 	hdr = heap->heap_allocated;
49100 	while (hdr != NULL) {
49101 		/* A finalizer is looked up from the object and up its
49102 		 * prototype chain (which allows inherited finalizers).
49103 		 * The finalizer is checked for using a duk_hobject flag
49104 		 * which is kept in sync with the presence and callability
49105 		 * of a _Finalizer hidden symbol.
49106 		 */
49107 
49108 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr) &&
49109 		    DUK_HEAPHDR_IS_OBJECT(hdr) &&
49110 		    !DUK_HEAPHDR_HAS_FINALIZED(hdr) &&
49111 		    DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr)) {
49112 			/* heaphdr:
49113 			 *  - is not reachable
49114 			 *  - is an object
49115 			 *  - is not a finalized object waiting for rescue/keep decision
49116 			 *  - has a finalizer
49117 			 */
49118 
49119 			DUK_DD(DUK_DDPRINT("unreachable heap object will be "
49120 			                   "finalized -> mark as finalizable "
49121 			                   "and treat as a reachability root: %p",
49122 			                   (void *) hdr));
49123 			DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
49124 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
49125 			count_finalizable++;
49126 		}
49127 
49128 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49129 	}
49130 
49131 	if (count_finalizable == 0) {
49132 		return;
49133 	}
49134 
49135 	DUK_DD(DUK_DDPRINT("marked %ld heap objects as finalizable, now mark them reachable",
49136 	                   (long) count_finalizable));
49137 
49138 	hdr = heap->heap_allocated;
49139 	while (hdr != NULL) {
49140 		if (DUK_HEAPHDR_HAS_FINALIZABLE(hdr)) {
49141 			duk__mark_heaphdr_nonnull(heap, hdr);
49142 		}
49143 
49144 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49145 	}
49146 
49147 	/* Caller will finish the marking process if we hit a recursion limit. */
49148 }
49149 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49150 
49151 /*
49152  *  Mark objects on finalize_list.
49153  */
49154 
49155 #if defined(DUK_USE_FINALIZER_SUPPORT)
49156 DUK_LOCAL void duk__mark_finalize_list(duk_heap *heap) {
49157 	duk_heaphdr *hdr;
49158 #if defined(DUK_USE_DEBUG)
49159 	duk_size_t count_finalize_list = 0;
49160 #endif
49161 
49162 	DUK_DD(DUK_DDPRINT("duk__mark_finalize_list: %p", (void *) heap));
49163 
49164 	hdr = heap->finalize_list;
49165 	while (hdr != NULL) {
49166 		duk__mark_heaphdr_nonnull(heap, hdr);
49167 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49168 #if defined(DUK_USE_DEBUG)
49169 		count_finalize_list++;
49170 #endif
49171 	}
49172 
49173 #if defined(DUK_USE_DEBUG)
49174 	if (count_finalize_list > 0) {
49175 		DUK_D(DUK_DPRINT("marked %ld objects on the finalize_list as reachable (previous finalizer run skipped)",
49176 		                 (long) count_finalize_list));
49177 	}
49178 #endif
49179 }
49180 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49181 
49182 /*
49183  *  Fallback marking handler if recursion limit is reached.
49184  *
49185  *  Iterates 'temproots' until recursion limit is no longer hit.  Temproots
49186  *  can be in heap_allocated or finalize_list; refzero_list is now always
49187  *  empty for mark-and-sweep.  A temproot may occur in finalize_list now if
49188  *  there are objects on the finalize_list and user code creates a reference
49189  *  from an object in heap_allocated to the object in finalize_list (which is
49190  *  now allowed), and it happened to coincide with the recursion depth limit.
49191  *
49192  *  This is a slow scan, but guarantees that we finish with a bounded C stack.
49193  *
49194  *  Note that nodes may have been marked as temproots before this scan begun,
49195  *  OR they may have been marked during the scan (as we process nodes
49196  *  recursively also during the scan).  This is intended behavior.
49197  */
49198 
49199 #if defined(DUK_USE_DEBUG)
49200 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr, duk_size_t *count) {
49201 #else
49202 DUK_LOCAL void duk__handle_temproot(duk_heap *heap, duk_heaphdr *hdr) {
49203 #endif
49204 	DUK_ASSERT(hdr != NULL);
49205 
49206 	if (!DUK_HEAPHDR_HAS_TEMPROOT(hdr)) {
49207 		DUK_DDD(DUK_DDDPRINT("not a temp root: %p", (void *) hdr));
49208 		return;
49209 	}
49210 
49211 	DUK_DDD(DUK_DDDPRINT("found a temp root: %p", (void *) hdr));
49212 	DUK_HEAPHDR_CLEAR_TEMPROOT(hdr);
49213 	DUK_HEAPHDR_CLEAR_REACHABLE(hdr);  /* Done so that duk__mark_heaphdr() works correctly. */
49214 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
49215 	hdr->h_assert_refcount--;  /* Same node visited twice. */
49216 #endif
49217 	duk__mark_heaphdr_nonnull(heap, hdr);
49218 
49219 #if defined(DUK_USE_DEBUG)
49220 	(*count)++;
49221 #endif
49222 }
49223 
49224 DUK_LOCAL void duk__mark_temproots_by_heap_scan(duk_heap *heap) {
49225 	duk_heaphdr *hdr;
49226 #if defined(DUK_USE_DEBUG)
49227 	duk_size_t count;
49228 #endif
49229 
49230 	DUK_DD(DUK_DDPRINT("duk__mark_temproots_by_heap_scan: %p", (void *) heap));
49231 
49232 	while (DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap)) {
49233 		DUK_DD(DUK_DDPRINT("recursion limit reached, doing heap scan to continue from temproots"));
49234 
49235 #if defined(DUK_USE_DEBUG)
49236 		count = 0;
49237 #endif
49238 		DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap);
49239 
49240 		hdr = heap->heap_allocated;
49241 		while (hdr) {
49242 #if defined(DUK_USE_DEBUG)
49243 			duk__handle_temproot(heap, hdr, &count);
49244 #else
49245 			duk__handle_temproot(heap, hdr);
49246 #endif
49247 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49248 		}
49249 
49250 #if defined(DUK_USE_FINALIZER_SUPPORT)
49251 		hdr = heap->finalize_list;
49252 		while (hdr) {
49253 #if defined(DUK_USE_DEBUG)
49254 			duk__handle_temproot(heap, hdr, &count);
49255 #else
49256 			duk__handle_temproot(heap, hdr);
49257 #endif
49258 			hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49259 		}
49260 #endif
49261 
49262 #if defined(DUK_USE_DEBUG)
49263 		DUK_DD(DUK_DDPRINT("temproot mark heap scan processed %ld temp roots", (long) count));
49264 #endif
49265 	}
49266 }
49267 
49268 /*
49269  *  Finalize refcounts for heap elements just about to be freed.
49270  *  This must be done for all objects before freeing to avoid any
49271  *  stale pointer dereferences.
49272  *
49273  *  Note that this must deduce the set of objects to be freed
49274  *  identically to duk__sweep_heap().
49275  */
49276 
49277 #if defined(DUK_USE_REFERENCE_COUNTING)
49278 DUK_LOCAL void duk__finalize_refcounts(duk_heap *heap) {
49279 	duk_heaphdr *hdr;
49280 
49281 	DUK_ASSERT(heap->heap_thread != NULL);
49282 
49283 	DUK_DD(DUK_DDPRINT("duk__finalize_refcounts: heap=%p", (void *) heap));
49284 
49285 	hdr = heap->heap_allocated;
49286 	while (hdr) {
49287 		if (!DUK_HEAPHDR_HAS_REACHABLE(hdr)) {
49288 			/*
49289 			 *  Unreachable object about to be swept.  Finalize target refcounts
49290 			 *  (objects which the unreachable object points to) without doing
49291 			 *  refzero processing.  Recursive decrefs are also prevented when
49292 			 *  refzero processing is disabled.
49293 			 *
49294 			 *  Value cannot be a finalizable object, as they have been made
49295 			 *  temporarily reachable for this round.
49296 			 */
49297 
49298 			DUK_DDD(DUK_DDDPRINT("unreachable object, refcount finalize before sweeping: %p", (void *) hdr));
49299 
49300 			/* Finalize using heap->heap_thread; DECREF has a
49301 			 * suppress check for mark-and-sweep which is based
49302 			 * on heap->ms_running.
49303 			 */
49304 			duk_heaphdr_refcount_finalize_norz(heap, hdr);
49305 		}
49306 
49307 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49308 	}
49309 }
49310 #endif  /* DUK_USE_REFERENCE_COUNTING */
49311 
49312 /*
49313  *  Clear (reachable) flags of finalize_list.
49314  *
49315  *  We could mostly do in the sweep phase when we move objects from the
49316  *  heap into the finalize_list.  However, if a finalizer run is skipped
49317  *  during a mark-and-sweep, the objects on the finalize_list will be marked
49318  *  reachable during the next mark-and-sweep.  Since they're already on the
49319  *  finalize_list, no-one will be clearing their REACHABLE flag so we do it
49320  *  here.  (This now overlaps with the sweep handling in a harmless way.)
49321  */
49322 
49323 #if defined(DUK_USE_FINALIZER_SUPPORT)
49324 DUK_LOCAL void duk__clear_finalize_list_flags(duk_heap *heap) {
49325 	duk_heaphdr *hdr;
49326 
49327 	DUK_DD(DUK_DDPRINT("duk__clear_finalize_list_flags: %p", (void *) heap));
49328 
49329 	hdr = heap->finalize_list;
49330 	while (hdr) {
49331 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
49332 #if defined(DUK_USE_ASSERTIONS)
49333 		DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZABLE(hdr) || \
49334 		           (heap->currently_finalizing == hdr));
49335 #endif
49336 		/* DUK_HEAPHDR_FLAG_FINALIZED may be set. */
49337 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
49338 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49339 	}
49340 }
49341 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49342 
49343 /*
49344  *  Sweep stringtable.
49345  */
49346 
49347 DUK_LOCAL void duk__sweep_stringtable(duk_heap *heap, duk_size_t *out_count_keep) {
49348 	duk_hstring *h;
49349 	duk_hstring *prev;
49350 	duk_uint32_t i;
49351 #if defined(DUK_USE_DEBUG)
49352 	duk_size_t count_free = 0;
49353 #endif
49354 	duk_size_t count_keep = 0;
49355 
49356 	DUK_DD(DUK_DDPRINT("duk__sweep_stringtable: %p", (void *) heap));
49357 
49358 #if defined(DUK_USE_STRTAB_PTRCOMP)
49359 	if (heap->strtable16 == NULL) {
49360 #else
49361 	if (heap->strtable == NULL) {
49362 #endif
49363 		goto done;
49364 	}
49365 
49366 	for (i = 0; i < heap->st_size; i++) {
49367 #if defined(DUK_USE_STRTAB_PTRCOMP)
49368 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49369 #else
49370 		h = heap->strtable[i];
49371 #endif
49372 		prev = NULL;
49373 		while (h != NULL) {
49374 			duk_hstring *next;
49375 			next = h->hdr.h_next;
49376 
49377 			if (DUK_HEAPHDR_HAS_REACHABLE((duk_heaphdr *) h))
49378 			{
49379 				DUK_HEAPHDR_CLEAR_REACHABLE((duk_heaphdr *) h);
49380 				count_keep++;
49381 				prev = h;
49382 			} else {
49383 #if defined(DUK_USE_DEBUG)
49384 				count_free++;
49385 #endif
49386 
49387 				/* For pinned strings the refcount has been
49388 				 * bumped.  We could unbump it here before
49389 				 * freeing, but that's actually not necessary
49390 				 * except for assertions.
49391 				 */
49392 #if 0
49393 				if (DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
49394 					DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) > 0U);
49395 					DUK_HSTRING_DECREF_NORZ(heap->heap_thread, h);
49396 					DUK_HSTRING_CLEAR_PINNED_LITERAL(h);
49397 				}
49398 #endif
49399 #if defined(DUK_USE_REFERENCE_COUNTING)
49400 				/* Non-zero refcounts should not happen for unreachable strings,
49401 				 * because we refcount finalize all unreachable objects which
49402 				 * should have decreased unreachable string refcounts to zero
49403 				 * (even for cycles).  However, pinned strings have a +1 bump.
49404 				 */
49405 				DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) ==
49406 				           DUK_HSTRING_HAS_PINNED_LITERAL(h) ? 1U : 0U);
49407 #endif
49408 
49409 				/* Deal with weak references first. */
49410 				duk_heap_strcache_string_remove(heap, (duk_hstring *) h);
49411 
49412 				/* Remove the string from the string table. */
49413 				duk_heap_strtable_unlink_prev(heap, (duk_hstring *) h, (duk_hstring *) prev);
49414 
49415 				/* Free inner references (these exist e.g. when external
49416 				 * strings are enabled) and the struct itself.
49417 				 */
49418 				duk_free_hstring(heap, (duk_hstring *) h);
49419 
49420 				/* Don't update 'prev'; it should be last string kept. */
49421 			}
49422 
49423 			h = next;
49424 		}
49425 	}
49426 
49427  done:
49428 #if defined(DUK_USE_DEBUG)
49429 	DUK_D(DUK_DPRINT("mark-and-sweep sweep stringtable: %ld freed, %ld kept",
49430 	                 (long) count_free, (long) count_keep));
49431 #endif
49432 	*out_count_keep = count_keep;
49433 }
49434 
49435 /*
49436  *  Sweep heap.
49437  */
49438 
49439 DUK_LOCAL void duk__sweep_heap(duk_heap *heap, duk_small_uint_t flags, duk_size_t *out_count_keep) {
49440 	duk_heaphdr *prev;  /* last element that was left in the heap */
49441 	duk_heaphdr *curr;
49442 	duk_heaphdr *next;
49443 #if defined(DUK_USE_DEBUG)
49444 	duk_size_t count_free = 0;
49445 	duk_size_t count_finalize = 0;
49446 	duk_size_t count_rescue = 0;
49447 #endif
49448 	duk_size_t count_keep = 0;
49449 
49450 	DUK_DD(DUK_DDPRINT("duk__sweep_heap: %p", (void *) heap));
49451 
49452 	prev = NULL;
49453 	curr = heap->heap_allocated;
49454 	heap->heap_allocated = NULL;
49455 	while (curr) {
49456 		/* Strings and ROM objects are never placed on the heap allocated list. */
49457 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_STRING);
49458 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));
49459 
49460 		next = DUK_HEAPHDR_GET_NEXT(heap, curr);
49461 
49462 		if (DUK_HEAPHDR_HAS_REACHABLE(curr)) {
49463 			/*
49464 			 *  Reachable object:
49465 			 *    - If FINALIZABLE -> actually unreachable (but marked
49466 			 *      artificially reachable), queue to finalize_list.
49467 			 *    - If !FINALIZABLE but FINALIZED -> rescued after
49468 			 *      finalizer execution.
49469 			 *    - Otherwise just a normal, reachable object.
49470 			 *
49471 			 *  Objects which are kept are queued to heap_allocated
49472 			 *  tail (we're essentially filtering heap_allocated in
49473 			 *  practice).
49474 			 */
49475 
49476 #if defined(DUK_USE_FINALIZER_SUPPORT)
49477 			if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZABLE(curr))) {
49478 				DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
49479 				DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49480 				DUK_DD(DUK_DDPRINT("sweep; reachable, finalizable --> move to finalize_list: %p", (void *) curr));
49481 
49482 #if defined(DUK_USE_REFERENCE_COUNTING)
49483 				DUK_HEAPHDR_PREINC_REFCOUNT(curr);  /* Bump refcount so that refzero never occurs when pending a finalizer call. */
49484 #endif
49485 				DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, curr);
49486 #if defined(DUK_USE_DEBUG)
49487 				count_finalize++;
49488 #endif
49489 			}
49490 			else
49491 #endif  /* DUK_USE_FINALIZER_SUPPORT */
49492 			{
49493 				if (DUK_UNLIKELY(DUK_HEAPHDR_HAS_FINALIZED(curr))) {
49494 					DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49495 					DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);
49496 
49497 					if (flags & DUK_MS_FLAG_POSTPONE_RESCUE) {
49498 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized, but postponing rescue decisions --> keep object (with FINALIZED set): %!iO", curr));
49499 						count_keep++;
49500 					} else {
49501 						DUK_DD(DUK_DDPRINT("sweep; reachable, finalized --> rescued after finalization: %p", (void *) curr));
49502 #if defined(DUK_USE_FINALIZER_SUPPORT)
49503 						DUK_HEAPHDR_CLEAR_FINALIZED(curr);
49504 #endif
49505 #if defined(DUK_USE_DEBUG)
49506 						count_rescue++;
49507 #endif
49508 					}
49509 				} else {
49510 					DUK_DD(DUK_DDPRINT("sweep; reachable --> keep: %!iO", curr));
49511 					count_keep++;
49512 				}
49513 
49514 				if (prev != NULL) {
49515 					DUK_ASSERT(heap->heap_allocated != NULL);
49516 					DUK_HEAPHDR_SET_NEXT(heap, prev, curr);
49517 				} else {
49518 					DUK_ASSERT(heap->heap_allocated == NULL);
49519 					heap->heap_allocated = curr;
49520 				}
49521 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
49522 				DUK_HEAPHDR_SET_PREV(heap, curr, prev);
49523 #endif
49524 				DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
49525 				DUK_ASSERT_HEAPHDR_LINKS(heap, curr);
49526 				prev = curr;
49527 			}
49528 
49529 			/*
49530 			 *  Shrink check for value stacks here.  We're inside
49531 			 *  ms_prevent_count protection which prevents recursive
49532 			 *  mark-and-sweep and refzero finalizers, so there are
49533 			 *  no side effects that would affect the heap lists.
49534 			 */
49535 			if (DUK_HEAPHDR_IS_OBJECT(curr) && DUK_HOBJECT_IS_THREAD((duk_hobject *) curr)) {
49536 				duk_hthread *thr_curr = (duk_hthread *) curr;
49537 				DUK_DD(DUK_DDPRINT("value stack shrink check for thread: %!O", curr));
49538 				duk_valstack_shrink_check_nothrow(thr_curr, flags & DUK_MS_FLAG_EMERGENCY /*snug*/);
49539 			}
49540 
49541 			DUK_HEAPHDR_CLEAR_REACHABLE(curr);
49542 			/* Keep FINALIZED if set, used if rescue decisions are postponed. */
49543 			/* Keep FINALIZABLE for objects on finalize_list. */
49544 			DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(curr));
49545 		} else {
49546 			/*
49547 			 *  Unreachable object:
49548 			 *    - If FINALIZED, object was finalized but not
49549 			 *      rescued.  This doesn't affect freeing.
49550 			 *    - Otherwise normal unreachable object.
49551 			 *
49552 			 *  There's no guard preventing a FINALIZED object
49553 			 *  from being freed while finalizers execute: the
49554 			 *  artificial finalize_list reachability roots can't
49555 			 *  cause an incorrect free decision (but can cause
49556 			 *  an incorrect rescue decision).
49557 			 */
49558 
49559 #if defined(DUK_USE_REFERENCE_COUNTING)
49560 			/* Non-zero refcounts should not happen because we refcount
49561 			 * finalize all unreachable objects which should cancel out
49562 			 * refcounts (even for cycles).
49563 			 */
49564 			DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(curr) == 0);
49565 #endif
49566 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(curr));
49567 
49568 #if defined(DUK_USE_DEBUG)
49569 			if (DUK_HEAPHDR_HAS_FINALIZED(curr)) {
49570 				DUK_DD(DUK_DDPRINT("sweep; unreachable, finalized --> finalized object not rescued: %p", (void *) curr));
49571 			} else {
49572 				DUK_DD(DUK_DDPRINT("sweep; not reachable --> free: %p", (void *) curr));
49573 			}
49574 
49575 #endif
49576 
49577 			/* Note: object cannot be a finalizable unreachable object, as
49578 			 * they have been marked temporarily reachable for this round,
49579 			 * and are handled above.
49580 			 */
49581 
49582 #if defined(DUK_USE_DEBUG)
49583 			count_free++;
49584 #endif
49585 
49586 			/* Weak refs should be handled here, but no weak refs for
49587 			 * any non-string objects exist right now.
49588 			 */
49589 
49590 			/* Free object and all auxiliary (non-heap) allocs. */
49591 			duk_heap_free_heaphdr_raw(heap, curr);
49592 		}
49593 
49594 		curr = next;
49595 	}
49596 
49597 	if (prev != NULL) {
49598 		DUK_HEAPHDR_SET_NEXT(heap, prev, NULL);
49599 	}
49600 	DUK_ASSERT_HEAPHDR_LINKS(heap, prev);
49601 
49602 #if defined(DUK_USE_DEBUG)
49603 	DUK_D(DUK_DPRINT("mark-and-sweep sweep objects (non-string): %ld freed, %ld kept, %ld rescued, %ld queued for finalization",
49604 	                 (long) count_free, (long) count_keep, (long) count_rescue, (long) count_finalize));
49605 #endif
49606 	*out_count_keep = count_keep;
49607 }
49608 
49609 /*
49610  *  Litcache helpers.
49611  */
49612 
49613 #if defined(DUK_USE_LITCACHE_SIZE)
49614 DUK_LOCAL void duk__wipe_litcache(duk_heap *heap) {
49615 	duk_uint_t i;
49616 	duk_litcache_entry *e;
49617 
49618 	e = heap->litcache;
49619 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
49620 		e->addr = NULL;
49621 		/* e->h does not need to be invalidated: when e->addr is
49622 		 * NULL, e->h is considered garbage.
49623 		 */
49624 		e++;
49625 	}
49626 }
49627 #endif  /* DUK_USE_LITCACHE_SIZE */
49628 
49629 /*
49630  *  Object compaction.
49631  *
49632  *  Compaction is assumed to never throw an error.
49633  */
49634 
49635 DUK_LOCAL int duk__protected_compact_object(duk_hthread *thr, void *udata) {
49636 	duk_hobject *obj;
49637 	/* XXX: for threads, compact stacks? */
49638 
49639 	DUK_UNREF(udata);
49640 	obj = duk_known_hobject(thr, -1);
49641 	duk_hobject_compact_props(thr, obj);
49642 	return 0;
49643 }
49644 
49645 #if defined(DUK_USE_DEBUG)
49646 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) {
49647 #else
49648 DUK_LOCAL void duk__compact_object_list(duk_heap *heap, duk_hthread *thr, duk_heaphdr *start) {
49649 #endif
49650 	duk_heaphdr *curr;
49651 #if defined(DUK_USE_DEBUG)
49652 	duk_size_t old_size, new_size;
49653 #endif
49654 	duk_hobject *obj;
49655 
49656 	DUK_UNREF(heap);
49657 
49658 	curr = start;
49659 	while (curr) {
49660 		DUK_DDD(DUK_DDDPRINT("mark-and-sweep compact: %p", (void *) curr));
49661 
49662 		if (DUK_HEAPHDR_GET_TYPE(curr) != DUK_HTYPE_OBJECT) {
49663 			goto next;
49664 		}
49665 		obj = (duk_hobject *) curr;
49666 
49667 #if defined(DUK_USE_DEBUG)
49668 		old_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49669 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49670 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49671 #endif
49672 
49673 		DUK_DD(DUK_DDPRINT("compact object: %p", (void *) obj));
49674 		duk_push_hobject(thr, obj);
49675 		/* XXX: disable error handlers for duration of compaction? */
49676 		duk_safe_call(thr, duk__protected_compact_object, NULL, 1, 0);
49677 
49678 #if defined(DUK_USE_DEBUG)
49679 		new_size = DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
49680 		                                      DUK_HOBJECT_GET_ASIZE(obj),
49681 		                                      DUK_HOBJECT_GET_HSIZE(obj));
49682 #endif
49683 
49684 #if defined(DUK_USE_DEBUG)
49685 		(*p_count_compact)++;
49686 		(*p_count_bytes_saved) += (duk_size_t) (old_size - new_size);
49687 #endif
49688 
49689 	 next:
49690 		curr = DUK_HEAPHDR_GET_NEXT(heap, curr);
49691 #if defined(DUK_USE_DEBUG)
49692 		(*p_count_check)++;
49693 #endif
49694 	}
49695 }
49696 
49697 DUK_LOCAL void duk__compact_objects(duk_heap *heap) {
49698 	/* XXX: which lists should participate?  to be finalized? */
49699 #if defined(DUK_USE_DEBUG)
49700 	duk_size_t count_check = 0;
49701 	duk_size_t count_compact = 0;
49702 	duk_size_t count_bytes_saved = 0;
49703 #endif
49704 
49705 	DUK_DD(DUK_DDPRINT("duk__compact_objects: %p", (void *) heap));
49706 
49707 	DUK_ASSERT(heap->heap_thread != NULL);
49708 
49709 #if defined(DUK_USE_DEBUG)
49710 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated, &count_check, &count_compact, &count_bytes_saved);
49711 #if defined(DUK_USE_FINALIZER_SUPPORT)
49712 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list, &count_check, &count_compact, &count_bytes_saved);
49713 #endif
49714 #else
49715 	duk__compact_object_list(heap, heap->heap_thread, heap->heap_allocated);
49716 #if defined(DUK_USE_FINALIZER_SUPPORT)
49717 	duk__compact_object_list(heap, heap->heap_thread, heap->finalize_list);
49718 #endif
49719 #endif
49720 #if defined(DUK_USE_REFERENCE_COUNTING)
49721 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49722 #endif
49723 
49724 #if defined(DUK_USE_DEBUG)
49725 	DUK_D(DUK_DPRINT("mark-and-sweep compact objects: %ld checked, %ld compaction attempts, %ld bytes saved by compaction",
49726 	                 (long) count_check, (long) count_compact, (long) count_bytes_saved));
49727 #endif
49728 }
49729 
49730 /*
49731  *  Assertion helpers.
49732  */
49733 
49734 #if defined(DUK_USE_ASSERTIONS)
49735 DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
49736 	duk_heaphdr *hdr;
49737 
49738 	hdr = heap->heap_allocated;
49739 	while (hdr) {
49740 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
49741 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
49742 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
49743 		/* may have FINALIZED */
49744 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49745 	}
49746 
49747 #if defined(DUK_USE_REFERENCE_COUNTING)
49748 	DUK_ASSERT(heap->refzero_list == NULL);  /* Always handled to completion inline in DECREF. */
49749 #endif
49750 }
49751 
49752 #if defined(DUK_USE_REFERENCE_COUNTING)
49753 DUK_LOCAL void duk__assert_valid_refcounts(duk_heap *heap) {
49754 	duk_heaphdr *hdr = heap->heap_allocated;
49755 	while (hdr) {
49756 		/* Cannot really assert much w.r.t. refcounts now. */
49757 
49758 		if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0 &&
49759 		    DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
49760 			/* An object may be in heap_allocated list with a zero
49761 			 * refcount if it has just been finalized and is waiting
49762 			 * to be collected by the next cycle.
49763 			 * (This doesn't currently happen however.)
49764 			 */
49765 		} else if (DUK_HEAPHDR_GET_REFCOUNT(hdr) == 0) {
49766 			/* An object may be in heap_allocated list with a zero
49767 			 * refcount also if it is a temporary object created
49768 			 * during debugger paused state.  It will get collected
49769 			 * by mark-and-sweep based on its reachability status
49770 			 * (presumably not reachable because refcount is 0).
49771 			 */
49772 		}
49773 		DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(hdr) >= 0);  /* Unsigned. */
49774 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
49775 	}
49776 }
49777 
49778 DUK_LOCAL void duk__clear_assert_refcounts(duk_heap *heap) {
49779 	duk_heaphdr *curr;
49780 	duk_uint32_t i;
49781 
49782 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49783 		curr->h_assert_refcount = 0;
49784 	}
49785 #if defined(DUK_USE_FINALIZER_SUPPORT)
49786 	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49787 		curr->h_assert_refcount = 0;
49788 	}
49789 #endif
49790 #if defined(DUK_USE_REFERENCE_COUNTING)
49791 	for (curr = heap->refzero_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49792 		curr->h_assert_refcount = 0;
49793 	}
49794 #endif
49795 
49796 	for (i = 0; i < heap->st_size; i++) {
49797 		duk_hstring *h;
49798 
49799 #if defined(DUK_USE_STRTAB_PTRCOMP)
49800 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49801 #else
49802 		h = heap->strtable[i];
49803 #endif
49804 		while (h != NULL) {
49805 			((duk_heaphdr *) h)->h_assert_refcount = 0;
49806 			h = h->hdr.h_next;
49807 		}
49808 	}
49809 }
49810 
49811 DUK_LOCAL void duk__check_refcount_heaphdr(duk_heaphdr *hdr) {
49812 	duk_bool_t count_ok;
49813 	duk_size_t expect_refc;
49814 
49815 	/* The refcount check only makes sense for reachable objects on
49816 	 * heap_allocated or string table, after the sweep phase.  Prior to
49817 	 * sweep phase refcounts will include references that are not visible
49818 	 * via reachability roots.
49819 	 *
49820 	 * Because we're called after the sweep phase, all heap objects on
49821 	 * heap_allocated are reachable.  REACHABLE flags have already been
49822 	 * cleared so we can't check them.
49823 	 */
49824 
49825 	/* ROM objects have intentionally incorrect refcount (1), but we won't
49826 	 * check them.
49827 	 */
49828 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(hdr));
49829 
49830 	expect_refc = hdr->h_assert_refcount;
49831 	if (DUK_HEAPHDR_IS_STRING(hdr) && DUK_HSTRING_HAS_PINNED_LITERAL((duk_hstring *) hdr)) {
49832 		expect_refc++;
49833 	}
49834 	count_ok = ((duk_size_t) DUK_HEAPHDR_GET_REFCOUNT(hdr) == expect_refc);
49835 	if (!count_ok) {
49836 		DUK_D(DUK_DPRINT("refcount mismatch for: %p: header=%ld counted=%ld --> %!iO",
49837 		                 (void *) hdr, (long) DUK_HEAPHDR_GET_REFCOUNT(hdr),
49838 		                 (long) hdr->h_assert_refcount, hdr));
49839 		DUK_ASSERT(0);
49840 	}
49841 }
49842 
49843 DUK_LOCAL void duk__check_assert_refcounts(duk_heap *heap) {
49844 	duk_heaphdr *curr;
49845 	duk_uint32_t i;
49846 
49847 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49848 		duk__check_refcount_heaphdr(curr);
49849 	}
49850 #if defined(DUK_USE_FINALIZER_SUPPORT)
49851 	for (curr = heap->finalize_list; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
49852 		duk__check_refcount_heaphdr(curr);
49853 	}
49854 #endif
49855 
49856 	for (i = 0; i < heap->st_size; i++) {
49857 		duk_hstring *h;
49858 
49859 #if defined(DUK_USE_STRTAB_PTRCOMP)
49860 		h = DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
49861 #else
49862 		h = heap->strtable[i];
49863 #endif
49864 		while (h != NULL) {
49865 			duk__check_refcount_heaphdr((duk_heaphdr *) h);
49866 			h = h->hdr.h_next;
49867 		}
49868 	}
49869 }
49870 #endif  /* DUK_USE_REFERENCE_COUNTING */
49871 
49872 #if defined(DUK_USE_LITCACHE_SIZE)
49873 DUK_LOCAL void duk__assert_litcache_nulls(duk_heap *heap) {
49874 	duk_uint_t i;
49875 	duk_litcache_entry *e;
49876 
49877 	e = heap->litcache;
49878 	for (i = 0; i < DUK_USE_LITCACHE_SIZE; i++) {
49879 		/* Entry addresses were NULLed before mark-and-sweep, check
49880 		 * that they're still NULL afterwards to ensure no pointers
49881 		 * were recorded through any side effects.
49882 		 */
49883 		DUK_ASSERT(e->addr == NULL);
49884 	}
49885 }
49886 #endif  /* DUK_USE_LITCACHE_SIZE */
49887 #endif  /* DUK_USE_ASSERTIONS */
49888 
49889 /*
49890  *  Stats dump.
49891  */
49892 
49893 #if defined(DUK_USE_DEBUG)
49894 DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
49895 	DUK_D(DUK_DPRINT("stats executor: opcodes=%ld, interrupt=%ld, throw=%ld",
49896 	                 (long) heap->stats_exec_opcodes, (long) heap->stats_exec_interrupt,
49897 	                 (long) heap->stats_exec_throw));
49898 	DUK_D(DUK_DPRINT("stats call: all=%ld, tailcall=%ld, ecmatoecma=%ld",
49899 	                 (long) heap->stats_call_all, (long) heap->stats_call_tailcall,
49900 	                 (long) heap->stats_call_ecmatoecma));
49901 	DUK_D(DUK_DPRINT("stats safecall: all=%ld, nothrow=%ld, throw=%ld",
49902 	                 (long) heap->stats_safecall_all, (long) heap->stats_safecall_nothrow,
49903 	                 (long) heap->stats_safecall_throw));
49904 	DUK_D(DUK_DPRINT("stats mark-and-sweep: try_count=%ld, skip_count=%ld, emergency_count=%ld",
49905 	                 (long) heap->stats_ms_try_count, (long) heap->stats_ms_skip_count,
49906 	                 (long) heap->stats_ms_emergency_count));
49907 	DUK_D(DUK_DPRINT("stats stringtable: intern_hit=%ld, intern_miss=%ld, "
49908 	                 "resize_check=%ld, resize_grow=%ld, resize_shrink=%ld, "
49909 	                 "litcache_hit=%ld, litcache_miss=%ld, litcache_pin=%ld",
49910 	                 (long) heap->stats_strtab_intern_hit, (long) heap->stats_strtab_intern_miss,
49911 	                 (long) heap->stats_strtab_resize_check, (long) heap->stats_strtab_resize_grow,
49912 	                 (long) heap->stats_strtab_resize_shrink, (long) heap->stats_strtab_litcache_hit,
49913 	                 (long) heap->stats_strtab_litcache_miss, (long) heap->stats_strtab_litcache_pin));
49914 	DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
49915 	                 (long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
49916 	DUK_D(DUK_DPRINT("stats getownpropdesc: count=%ld, hit=%ld, miss=%ld",
49917 	                 (long) heap->stats_getownpropdesc_count, (long) heap->stats_getownpropdesc_hit,
49918 	                 (long) heap->stats_getownpropdesc_miss));
49919 	DUK_D(DUK_DPRINT("stats getpropdesc: count=%ld, hit=%ld, miss=%ld",
49920 	                 (long) heap->stats_getpropdesc_count, (long) heap->stats_getpropdesc_hit,
49921 	                 (long) heap->stats_getpropdesc_miss));
49922 	DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
49923 	                 "bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
49924 	                 "proxy=%ld, arguments=%ld",
49925 	                 (long) heap->stats_getprop_all, (long) heap->stats_getprop_arrayidx,
49926 	                 (long) heap->stats_getprop_bufobjidx, (long) heap->stats_getprop_bufferidx,
49927 	                 (long) heap->stats_getprop_bufferlen, (long) heap->stats_getprop_stringidx,
49928 	                 (long) heap->stats_getprop_stringlen, (long) heap->stats_getprop_proxy,
49929 	                 (long) heap->stats_getprop_arguments));
49930 	DUK_D(DUK_DPRINT("stats putprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
49931 	                 "bufferidx=%ld, proxy=%ld",
49932 	                 (long) heap->stats_putprop_all, (long) heap->stats_putprop_arrayidx,
49933 	                 (long) heap->stats_putprop_bufobjidx, (long) heap->stats_putprop_bufferidx,
49934 	                 (long) heap->stats_putprop_proxy));
49935 	DUK_D(DUK_DPRINT("stats getvar: all=%ld",
49936 	                 (long) heap->stats_getvar_all));
49937 	DUK_D(DUK_DPRINT("stats putvar: all=%ld",
49938 	                 (long) heap->stats_putvar_all));
49939 }
49940 #endif  /* DUK_USE_DEBUG */
49941 
49942 /*
49943  *  Main mark-and-sweep function.
49944  *
49945  *  'flags' represents the features requested by the caller.  The current
49946  *  heap->ms_base_flags is ORed automatically into the flags; the base flags
49947  *  mask typically prevents certain mark-and-sweep operation to avoid trouble.
49948  */
49949 
49950 DUK_INTERNAL void duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags) {
49951 	duk_size_t count_keep_obj;
49952 	duk_size_t count_keep_str;
49953 #if defined(DUK_USE_VOLUNTARY_GC)
49954 	duk_size_t tmp;
49955 #endif
49956 
49957 	DUK_STATS_INC(heap, stats_ms_try_count);
49958 #if defined(DUK_USE_DEBUG)
49959 	if (flags & DUK_MS_FLAG_EMERGENCY) {
49960 		DUK_STATS_INC(heap, stats_ms_emergency_count);
49961 	}
49962 #endif
49963 
49964 	/* If debugger is paused, garbage collection is disabled by default.
49965 	 * This is achieved by bumping ms_prevent_count when becoming paused.
49966 	 */
49967 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) || heap->ms_prevent_count > 0);
49968 
49969 	/* Prevention/recursion check as soon as possible because we may
49970 	 * be called a number of times when voluntary mark-and-sweep is
49971 	 * pending.
49972 	 */
49973 	if (heap->ms_prevent_count != 0) {
49974 		DUK_DD(DUK_DDPRINT("reject recursive mark-and-sweep"));
49975 		DUK_STATS_INC(heap, stats_ms_skip_count);
49976 		return;
49977 	}
49978 	DUK_ASSERT(heap->ms_running == 0);  /* ms_prevent_count is bumped when ms_running is set */
49979 
49980 	/* Heap_thread is used during mark-and-sweep for refcount finalization
49981 	 * (it's also used for finalizer execution once mark-and-sweep is
49982 	 * complete).  Heap allocation code ensures heap_thread is set and
49983 	 * properly initialized before setting ms_prevent_count to 0.
49984 	 */
49985 	DUK_ASSERT(heap->heap_thread != NULL);
49986 	DUK_ASSERT(heap->heap_thread->valstack != NULL);
49987 
49988 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) starting, requested flags: 0x%08lx, effective flags: 0x%08lx",
49989 	                 (unsigned long) flags, (unsigned long) (flags | heap->ms_base_flags)));
49990 
49991 	flags |= heap->ms_base_flags;
49992 #if defined(DUK_USE_FINALIZER_SUPPORT)
49993 	if (heap->finalize_list != NULL) {
49994 		flags |= DUK_MS_FLAG_POSTPONE_RESCUE;
49995 	}
49996 #endif
49997 
49998 	/*
49999 	 *  Assertions before
50000 	 */
50001 
50002 #if defined(DUK_USE_ASSERTIONS)
50003 	DUK_ASSERT(heap->ms_prevent_count == 0);
50004 	DUK_ASSERT(heap->ms_running == 0);
50005 	DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(heap));
50006 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50007 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50008 	duk__assert_heaphdr_flags(heap);
50009 #if defined(DUK_USE_REFERENCE_COUNTING)
50010 	/* Note: heap->refzero_free_running may be true; a refcount
50011 	 * finalizer may trigger a mark-and-sweep.
50012 	 */
50013 	duk__assert_valid_refcounts(heap);
50014 #endif  /* DUK_USE_REFERENCE_COUNTING */
50015 #endif  /* DUK_USE_ASSERTIONS */
50016 
50017 	/*
50018 	 *  Begin
50019 	 */
50020 
50021 	DUK_ASSERT(heap->ms_prevent_count == 0);
50022 	DUK_ASSERT(heap->ms_running == 0);
50023 	heap->ms_prevent_count = 1;
50024 	heap->ms_running = 1;
50025 
50026 	/*
50027 	 *  Free activation/catcher freelists on every mark-and-sweep for now.
50028 	 *  This is an initial rough draft; ideally we'd keep count of the
50029 	 *  freelist size and free only excess entries.
50030 	 */
50031 
50032 	DUK_D(DUK_DPRINT("freeing temporary freelists"));
50033 	duk_heap_free_freelists(heap);
50034 
50035 	/*
50036 	 *  Mark roots, hoping that recursion limit is not normally hit.
50037 	 *  If recursion limit is hit, run additional reachability rounds
50038 	 *  starting from "temproots" until marking is complete.
50039 	 *
50040 	 *  Marking happens in two phases: first we mark actual reachability
50041 	 *  roots (and run "temproots" to complete the process).  Then we
50042 	 *  check which objects are unreachable and are finalizable; such
50043 	 *  objects are marked as FINALIZABLE and marked as reachability
50044 	 *  (and "temproots" is run again to complete the process).
50045 	 *
50046 	 *  The heap finalize_list must also be marked as a reachability root.
50047 	 *  There may be objects on the list from a previous round if the
50048 	 *  previous run had finalizer skip flag.
50049 	 */
50050 
50051 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50052 	duk__clear_assert_refcounts(heap);
50053 #endif
50054 #if defined(DUK_USE_LITCACHE_SIZE)
50055 	duk__wipe_litcache(heap);
50056 #endif
50057 	duk__mark_roots_heap(heap);               /* Mark main reachability roots. */
50058 #if defined(DUK_USE_REFERENCE_COUNTING)
50059 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50060 #endif
50061 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50062 
50063 #if defined(DUK_USE_FINALIZER_SUPPORT)
50064 	duk__mark_finalizable(heap);              /* Mark finalizable as reachability roots. */
50065 	duk__mark_finalize_list(heap);            /* Mark finalizer work list as reachability roots. */
50066 #endif
50067 	duk__mark_temproots_by_heap_scan(heap);   /* Temproots. */
50068 
50069 	/*
50070 	 *  Sweep garbage and remove marking flags, and move objects with
50071 	 *  finalizers to the finalizer work list.
50072 	 *
50073 	 *  Objects to be swept need to get their refcounts finalized before
50074 	 *  they are swept.  In other words, their target object refcounts
50075 	 *  need to be decreased.  This has to be done before freeing any
50076 	 *  objects to avoid decref'ing dangling pointers (which may happen
50077 	 *  even without bugs, e.g. with reference loops)
50078 	 *
50079 	 *  Because strings don't point to other heap objects, similar
50080 	 *  finalization is not necessary for strings.
50081 	 */
50082 
50083 	/* XXX: more emergency behavior, e.g. find smaller hash sizes etc */
50084 
50085 #if defined(DUK_USE_REFERENCE_COUNTING)
50086 	duk__finalize_refcounts(heap);
50087 #endif
50088 	duk__sweep_heap(heap, flags, &count_keep_obj);
50089 	duk__sweep_stringtable(heap, &count_keep_str);
50090 #if defined(DUK_USE_ASSERTIONS) && defined(DUK_USE_REFERENCE_COUNTING)
50091 	duk__check_assert_refcounts(heap);
50092 #endif
50093 #if defined(DUK_USE_REFERENCE_COUNTING)
50094 	DUK_ASSERT(heap->refzero_list == NULL);   /* Always handled to completion inline in DECREF. */
50095 #endif
50096 #if defined(DUK_USE_FINALIZER_SUPPORT)
50097 	duk__clear_finalize_list_flags(heap);
50098 #endif
50099 
50100 	/*
50101 	 *  Object compaction (emergency only).
50102 	 *
50103 	 *  Object compaction is a separate step after sweeping, as there is
50104 	 *  more free memory for it to work with.  Also, currently compaction
50105 	 *  may insert new objects into the heap allocated list and the string
50106 	 *  table which we don't want to do during a sweep (the reachability
50107 	 *  flags of such objects would be incorrect).  The objects inserted
50108 	 *  are currently:
50109 	 *
50110 	 *    - a temporary duk_hbuffer for a new properties allocation
50111 	 *    - if array part is abandoned, string keys are interned
50112 	 *
50113 	 *  The object insertions go to the front of the list, so they do not
50114 	 *  cause an infinite loop (they are not compacted).
50115 	 */
50116 
50117 	if ((flags & DUK_MS_FLAG_EMERGENCY) &&
50118 	    !(flags & DUK_MS_FLAG_NO_OBJECT_COMPACTION)) {
50119 		duk__compact_objects(heap);
50120 	}
50121 
50122 	/*
50123 	 *  String table resize check.
50124 	 *
50125 	 *  This is mainly useful in emergency GC: if the string table load
50126 	 *  factor is really low for some reason, we can shrink the string
50127 	 *  table to a smaller size and free some memory in the process.
50128 	 *  Only execute in emergency GC.  String table has internal flags
50129 	 *  to protect against recursive resizing if this mark-and-sweep pass
50130 	 *  was triggered by a string table resize.
50131 	 */
50132 
50133 	if (flags & DUK_MS_FLAG_EMERGENCY) {
50134 		DUK_D(DUK_DPRINT("stringtable resize check in emergency gc"));
50135 		duk_heap_strtable_force_resize(heap);
50136 	}
50137 
50138 	/*
50139 	 *  Finish
50140 	 */
50141 
50142 	DUK_ASSERT(heap->ms_prevent_count == 1);
50143 	heap->ms_prevent_count = 0;
50144 	DUK_ASSERT(heap->ms_running == 1);
50145 	heap->ms_running = 0;
50146 
50147 	/*
50148 	 *  Assertions after
50149 	 */
50150 
50151 #if defined(DUK_USE_ASSERTIONS)
50152 	DUK_ASSERT(heap->ms_prevent_count == 0);
50153 	DUK_ASSERT(!DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap));
50154 	DUK_ASSERT(heap->ms_recursion_depth == 0);
50155 	duk__assert_heaphdr_flags(heap);
50156 #if defined(DUK_USE_REFERENCE_COUNTING)
50157 	/* Note: heap->refzero_free_running may be true; a refcount
50158 	 * finalizer may trigger a mark-and-sweep.
50159 	 */
50160 	duk__assert_valid_refcounts(heap);
50161 #endif  /* DUK_USE_REFERENCE_COUNTING */
50162 #if defined(DUK_USE_LITCACHE_SIZE)
50163 	duk__assert_litcache_nulls(heap);
50164 #endif  /* DUK_USE_LITCACHE_SIZE */
50165 #endif  /* DUK_USE_ASSERTIONS */
50166 
50167 	/*
50168 	 *  Reset trigger counter
50169 	 */
50170 
50171 #if defined(DUK_USE_VOLUNTARY_GC)
50172 	tmp = (count_keep_obj + count_keep_str) / 256;
50173 	heap->ms_trigger_counter = (duk_int_t) (
50174 	    (tmp * DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT) +
50175 	    DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD);
50176 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, trigger reset to %ld",
50177 	                 (long) count_keep_obj, (long) count_keep_str, (long) heap->ms_trigger_counter));
50178 #else
50179 	DUK_D(DUK_DPRINT("garbage collect (mark-and-sweep) finished: %ld objects kept, %ld strings kept, no voluntary trigger",
50180 	                 (long) count_keep_obj, (long) count_keep_str));
50181 #endif
50182 
50183 	/*
50184 	 *  Stats dump
50185 	 */
50186 
50187 #if defined(DUK_USE_DEBUG)
50188 	duk__dump_stats(heap);
50189 #endif
50190 
50191 	/*
50192 	 *  Finalize objects in the finalization work list.  Finalized
50193 	 *  objects are queued back to heap_allocated with FINALIZED set.
50194 	 *
50195 	 *  Since finalizers may cause arbitrary side effects, they are
50196 	 *  prevented e.g. during string table and object property allocation
50197 	 *  resizing using heap->pf_prevent_count.  In this case the objects
50198 	 *  remain in the finalization work list after mark-and-sweep exits
50199 	 *  and they may be finalized on the next pass or any DECREF checking
50200 	 *  for finalize_list.
50201 	 *
50202 	 *  As of Duktape 2.1 finalization happens outside mark-and-sweep
50203 	 *  protection.  Mark-and-sweep is allowed while the finalize_list
50204 	 *  is being processed, but no rescue decisions are done while the
50205 	 *  process is on-going.  This avoids incorrect rescue decisions
50206 	 *  if an object is considered reachable (and thus rescued) because
50207 	 *  of a reference via finalize_list (which is considered a reachability
50208 	 *  root).  When finalize_list is being processed, reachable objects
50209 	 *  with FINALIZED set will just keep their FINALIZED flag for later
50210 	 *  mark-and-sweep processing.
50211 	 *
50212 	 *  This could also be handled (a bit better) by having a more refined
50213 	 *  notion of reachability for rescue/free decisions.
50214 	 *
50215 	 *  XXX: avoid finalizer execution when doing emergency GC?
50216 	 */
50217 
50218 #if defined(DUK_USE_FINALIZER_SUPPORT)
50219 	/* Attempt to process finalize_list, pf_prevent_count check
50220 	 * is inside the target.
50221 	 */
50222 	duk_heap_process_finalize_list(heap);
50223 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50224 }
50225 #line 1 "duk_heap_memory.c"
50226 /*
50227  *  Memory allocation handling.
50228  */
50229 
50230 /* #include duk_internal.h -> already included */
50231 
50232 /*
50233  *  Voluntary GC check
50234  */
50235 
50236 #if defined(DUK_USE_VOLUNTARY_GC)
50237 DUK_LOCAL DUK_INLINE void duk__check_voluntary_gc(duk_heap *heap) {
50238 	if (DUK_UNLIKELY(--(heap)->ms_trigger_counter < 0)) {
50239 #if defined(DUK_USE_DEBUG)
50240 		if (heap->ms_prevent_count == 0) {
50241 			DUK_D(DUK_DPRINT("triggering voluntary mark-and-sweep"));
50242 		} else {
50243 			DUK_DD(DUK_DDPRINT("gc blocked -> skip voluntary mark-and-sweep now"));
50244 		}
50245 #endif
50246 
50247 		/* Prevention checks in the call target handle cases where
50248 		 * voluntary GC is not allowed.  The voluntary GC trigger
50249 		 * counter is only rewritten if mark-and-sweep actually runs.
50250 		 */
50251 		duk_heap_mark_and_sweep(heap, DUK_MS_FLAG_VOLUNTARY /*flags*/);
50252 	}
50253 }
50254 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  do { duk__check_voluntary_gc((heap)); } while (0)
50255 #else
50256 #define DUK__VOLUNTARY_PERIODIC_GC(heap)  /* no voluntary gc */
50257 #endif  /* DUK_USE_VOLUNTARY_GC */
50258 
50259 /*
50260  *  Allocate memory with garbage collection
50261  */
50262 
50263 DUK_INTERNAL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size) {
50264 	void *res;
50265 	duk_small_int_t i;
50266 
50267 	DUK_ASSERT(heap != NULL);
50268 	DUK_ASSERT_DISABLE(size >= 0);
50269 
50270 	/*
50271 	 *  Voluntary periodic GC (if enabled)
50272 	 */
50273 
50274 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50275 
50276 	/*
50277 	 *  First attempt
50278 	 */
50279 
50280 #if defined(DUK_USE_GC_TORTURE)
50281 	/* Simulate alloc failure on every alloc, except when mark-and-sweep
50282 	 * is running.
50283 	 */
50284 	if (heap->ms_prevent_count == 0) {
50285 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first alloc attempt fails"));
50286 		res = NULL;
50287 		DUK_UNREF(res);
50288 		goto skip_attempt;
50289 	}
50290 #endif
50291 	res = heap->alloc_func(heap->heap_udata, size);
50292 	if (DUK_LIKELY(res || size == 0)) {
50293 		/* For zero size allocations NULL is allowed. */
50294 		return res;
50295 	}
50296 #if defined(DUK_USE_GC_TORTURE)
50297  skip_attempt:
50298 #endif
50299 
50300 	DUK_D(DUK_DPRINT("first alloc attempt failed, attempt to gc and retry"));
50301 
50302 #if 0
50303 	/*
50304 	 *  Avoid a GC if GC is already running.  This can happen at a late
50305 	 *  stage in a GC when we try to e.g. resize the stringtable
50306 	 *  or compact objects.
50307 	 *
50308 	 *  NOTE: explicit handling isn't actually be needed: if the GC is
50309 	 *  not allowed, duk_heap_mark_and_sweep() will reject it for every
50310 	 *  attempt in the loop below, resulting in a NULL same as here.
50311 	 */
50312 
50313 	if (heap->ms_prevent_count != 0) {
50314 		DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed, gc in progress (gc skipped), alloc size %ld", (long) size));
50315 		return NULL;
50316 	}
50317 #endif
50318 
50319 	/*
50320 	 *  Retry with several GC attempts.  Initial attempts are made without
50321 	 *  emergency mode; later attempts use emergency mode which minimizes
50322 	 *  memory allocations forcibly.
50323 	 */
50324 
50325 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50326 		duk_small_uint_t flags;
50327 
50328 		flags = 0;
50329 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50330 			flags |= DUK_MS_FLAG_EMERGENCY;
50331 		}
50332 
50333 		duk_heap_mark_and_sweep(heap, flags);
50334 
50335 		res = heap->alloc_func(heap->heap_udata, size);
50336 		if (res) {
50337 			DUK_D(DUK_DPRINT("duk_heap_mem_alloc() succeeded after gc (pass %ld), alloc size %ld",
50338 			                 (long) (i + 1), (long) size));
50339 			return res;
50340 		}
50341 	}
50342 
50343 	DUK_D(DUK_DPRINT("duk_heap_mem_alloc() failed even after gc, alloc size %ld", (long) size));
50344 	return NULL;
50345 }
50346 
50347 DUK_INTERNAL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size) {
50348 	void *res;
50349 
50350 	DUK_ASSERT(heap != NULL);
50351 	DUK_ASSERT_DISABLE(size >= 0);
50352 
50353 	res = DUK_ALLOC(heap, size);
50354 	if (DUK_LIKELY(res != NULL)) {
50355 		duk_memzero(res, size);
50356 	}
50357 	return res;
50358 }
50359 
50360 DUK_INTERNAL void *duk_heap_mem_alloc_checked(duk_hthread *thr, duk_size_t size) {
50361 	void *res;
50362 
50363 	DUK_ASSERT(thr != NULL);
50364 	res = duk_heap_mem_alloc(thr->heap, size);
50365 	if (DUK_LIKELY(res != NULL || size == 0)) {
50366 		return res;
50367 	}
50368 	DUK_ERROR_ALLOC_FAILED(thr);
50369 	DUK_WO_NORETURN(return NULL;);
50370 }
50371 
50372 DUK_INTERNAL void *duk_heap_mem_alloc_checked_zeroed(duk_hthread *thr, duk_size_t size) {
50373 	void *res;
50374 
50375 	DUK_ASSERT(thr != NULL);
50376 	res = duk_heap_mem_alloc_zeroed(thr->heap, size);
50377 	if (DUK_LIKELY(res != NULL || size == 0)) {
50378 		return res;
50379 	}
50380 	DUK_ERROR_ALLOC_FAILED(thr);
50381 	DUK_WO_NORETURN(return NULL;);
50382 }
50383 
50384 /*
50385  *  Reallocate memory with garbage collection
50386  */
50387 
50388 DUK_INTERNAL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize) {
50389 	void *res;
50390 	duk_small_int_t i;
50391 
50392 	DUK_ASSERT(heap != NULL);
50393 	/* ptr may be NULL */
50394 	DUK_ASSERT_DISABLE(newsize >= 0);
50395 
50396 	/*
50397 	 *  Voluntary periodic GC (if enabled)
50398 	 */
50399 
50400 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50401 
50402 	/*
50403 	 *  First attempt
50404 	 */
50405 
50406 #if defined(DUK_USE_GC_TORTURE)
50407 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50408 	 * is running.
50409 	 */
50410 	if (heap->ms_prevent_count == 0) {
50411 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first realloc attempt fails"));
50412 		res = NULL;
50413 		DUK_UNREF(res);
50414 		goto skip_attempt;
50415 	}
50416 #endif
50417 	res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50418 	if (DUK_LIKELY(res || newsize == 0)) {
50419 		/* For zero size allocations NULL is allowed. */
50420 		return res;
50421 	}
50422 #if defined(DUK_USE_GC_TORTURE)
50423  skip_attempt:
50424 #endif
50425 
50426 	DUK_D(DUK_DPRINT("first realloc attempt failed, attempt to gc and retry"));
50427 
50428 #if 0
50429 	/*
50430 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50431 	 */
50432 
50433 	if (heap->ms_prevent_count != 0) {
50434 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50435 		return NULL;
50436 	}
50437 #endif
50438 
50439 	/*
50440 	 *  Retry with several GC attempts.  Initial attempts are made without
50441 	 *  emergency mode; later attempts use emergency mode which minimizes
50442 	 *  memory allocations forcibly.
50443 	 */
50444 
50445 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50446 		duk_small_uint_t flags;
50447 
50448 		flags = 0;
50449 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50450 			flags |= DUK_MS_FLAG_EMERGENCY;
50451 		}
50452 
50453 		duk_heap_mark_and_sweep(heap, flags);
50454 
50455 		res = heap->realloc_func(heap->heap_udata, ptr, newsize);
50456 		if (res || newsize == 0) {
50457 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc() succeeded after gc (pass %ld), alloc size %ld",
50458 			                 (long) (i + 1), (long) newsize));
50459 			return res;
50460 		}
50461 	}
50462 
50463 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc() failed even after gc, alloc size %ld", (long) newsize));
50464 	return NULL;
50465 }
50466 
50467 /*
50468  *  Reallocate memory with garbage collection, using a callback to provide
50469  *  the current allocated pointer.  This variant is used when a mark-and-sweep
50470  *  (e.g. finalizers) might change the original pointer.
50471  */
50472 
50473 DUK_INTERNAL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize) {
50474 	void *res;
50475 	duk_small_int_t i;
50476 
50477 	DUK_ASSERT(heap != NULL);
50478 	DUK_ASSERT_DISABLE(newsize >= 0);
50479 
50480 	/*
50481 	 *  Voluntary periodic GC (if enabled)
50482 	 */
50483 
50484 	DUK__VOLUNTARY_PERIODIC_GC(heap);
50485 
50486 	/*
50487 	 *  First attempt
50488 	 */
50489 
50490 #if defined(DUK_USE_GC_TORTURE)
50491 	/* Simulate alloc failure on every realloc, except when mark-and-sweep
50492 	 * is running.
50493 	 */
50494 	if (heap->ms_prevent_count == 0) {
50495 		DUK_DDD(DUK_DDDPRINT("gc torture enabled, pretend that first indirect realloc attempt fails"));
50496 		res = NULL;
50497 		DUK_UNREF(res);
50498 		goto skip_attempt;
50499 	}
50500 #endif
50501 	res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50502 	if (DUK_LIKELY(res || newsize == 0)) {
50503 		/* For zero size allocations NULL is allowed. */
50504 		return res;
50505 	}
50506 #if defined(DUK_USE_GC_TORTURE)
50507  skip_attempt:
50508 #endif
50509 
50510 	DUK_D(DUK_DPRINT("first indirect realloc attempt failed, attempt to gc and retry"));
50511 
50512 #if 0
50513 	/*
50514 	 *  Avoid a GC if GC is already running.  See duk_heap_mem_alloc().
50515 	 */
50516 
50517 	if (heap->ms_prevent_count != 0) {
50518 		DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed, gc in progress (gc skipped), alloc size %ld", (long) newsize));
50519 		return NULL;
50520 	}
50521 #endif
50522 
50523 	/*
50524 	 *  Retry with several GC attempts.  Initial attempts are made without
50525 	 *  emergency mode; later attempts use emergency mode which minimizes
50526 	 *  memory allocations forcibly.
50527 	 */
50528 
50529 	for (i = 0; i < DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT; i++) {
50530 		duk_small_uint_t flags;
50531 
50532 #if defined(DUK_USE_DEBUG)
50533 		void *ptr_pre;
50534 		void *ptr_post;
50535 #endif
50536 
50537 #if defined(DUK_USE_DEBUG)
50538 		ptr_pre = cb(heap, ud);
50539 #endif
50540 		flags = 0;
50541 		if (i >= DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT - 1) {
50542 			flags |= DUK_MS_FLAG_EMERGENCY;
50543 		}
50544 
50545 		duk_heap_mark_and_sweep(heap, flags);
50546 #if defined(DUK_USE_DEBUG)
50547 		ptr_post = cb(heap, ud);
50548 		if (ptr_pre != ptr_post) {
50549 			DUK_DD(DUK_DDPRINT("realloc base pointer changed by mark-and-sweep: %p -> %p",
50550 			                   (void *) ptr_pre, (void *) ptr_post));
50551 		}
50552 #endif
50553 
50554 		/* Note: key issue here is to re-lookup the base pointer on every attempt.
50555 		 * The pointer being reallocated may change after every mark-and-sweep.
50556 		 */
50557 
50558 		res = heap->realloc_func(heap->heap_udata, cb(heap, ud), newsize);
50559 		if (res || newsize == 0) {
50560 			DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() succeeded after gc (pass %ld), alloc size %ld",
50561 			                 (long) (i + 1), (long) newsize));
50562 			return res;
50563 		}
50564 	}
50565 
50566 	DUK_D(DUK_DPRINT("duk_heap_mem_realloc_indirect() failed even after gc, alloc size %ld", (long) newsize));
50567 	return NULL;
50568 }
50569 
50570 /*
50571  *  Free memory
50572  */
50573 
50574 DUK_INTERNAL void duk_heap_mem_free(duk_heap *heap, void *ptr) {
50575 	DUK_ASSERT(heap != NULL);
50576 	/* ptr may be NULL */
50577 
50578 	/* Must behave like a no-op with NULL and any pointer returned from
50579 	 * malloc/realloc with zero size.
50580 	 */
50581 	heap->free_func(heap->heap_udata, ptr);
50582 
50583 	/* Never perform a GC (even voluntary) in a memory free, otherwise
50584 	 * all call sites doing frees would need to deal with the side effects.
50585 	 * No need to update voluntary GC counter either.
50586 	 */
50587 }
50588 
50589 /* automatic undefs */
50590 #undef DUK__VOLUNTARY_PERIODIC_GC
50591 #line 1 "duk_heap_misc.c"
50592 /*
50593  *  Support functions for duk_heap.
50594  */
50595 
50596 /* #include duk_internal.h -> already included */
50597 
50598 DUK_INTERNAL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50599 	duk_heaphdr *root;
50600 
50601 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50602 
50603 	root = heap->heap_allocated;
50604 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50605 	if (root != NULL) {
50606 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50607 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50608 	}
50609 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50610 #endif
50611 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50612 	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
50613 	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
50614 	heap->heap_allocated = hdr;
50615 }
50616 
50617 #if defined(DUK_USE_REFERENCE_COUNTING)
50618 DUK_INTERNAL void duk_heap_remove_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr) {
50619 	duk_heaphdr *prev;
50620 	duk_heaphdr *next;
50621 
50622 	/* Strings are in string table. */
50623 	DUK_ASSERT(hdr != NULL);
50624 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(hdr) != DUK_HTYPE_STRING);
50625 
50626 	/* Target 'hdr' must be in heap_allocated (not e.g. finalize_list).
50627 	 * If not, heap lists will become corrupted so assert early for it.
50628 	 */
50629 #if defined(DUK_USE_ASSERTIONS)
50630 	{
50631 		duk_heaphdr *tmp;
50632 		for (tmp = heap->heap_allocated; tmp != NULL; tmp = DUK_HEAPHDR_GET_NEXT(heap, tmp)) {
50633 			if (tmp == hdr) {
50634 				break;
50635 			}
50636 		}
50637 		DUK_ASSERT(tmp == hdr);
50638 	}
50639 #endif
50640 
50641 	/* Read/write only once to minimize pointer compression calls. */
50642 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50643 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50644 
50645 	if (prev != NULL) {
50646 		DUK_ASSERT(heap->heap_allocated != hdr);
50647 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50648 	} else {
50649 		DUK_ASSERT(heap->heap_allocated == hdr);
50650 		heap->heap_allocated = next;
50651 	}
50652 	if (next != NULL) {
50653 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50654 	} else {
50655 		;
50656 	}
50657 }
50658 #endif  /* DUK_USE_REFERENCE_COUNTING */
50659 
50660 #if defined(DUK_USE_FINALIZER_SUPPORT)
50661 DUK_INTERNAL void duk_heap_insert_into_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50662 	duk_heaphdr *root;
50663 
50664 	root = heap->finalize_list;
50665 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50666 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
50667 	if (root != NULL) {
50668 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
50669 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
50670 	}
50671 #endif
50672 	DUK_HEAPHDR_SET_NEXT(heap, hdr, root);
50673 	DUK_ASSERT_HEAPHDR_LINKS(heap, hdr);
50674 	DUK_ASSERT_HEAPHDR_LINKS(heap, root);
50675 	heap->finalize_list = hdr;
50676 }
50677 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50678 
50679 #if defined(DUK_USE_FINALIZER_SUPPORT)
50680 DUK_INTERNAL void duk_heap_remove_from_finalize_list(duk_heap *heap, duk_heaphdr *hdr) {
50681 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
50682 	duk_heaphdr *next;
50683 	duk_heaphdr *prev;
50684 
50685 	next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50686 	prev = DUK_HEAPHDR_GET_PREV(heap, hdr);
50687 	if (next != NULL) {
50688 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, next) == hdr);
50689 		DUK_HEAPHDR_SET_PREV(heap, next, prev);
50690 	}
50691 	if (prev == NULL) {
50692 		DUK_ASSERT(hdr == heap->finalize_list);
50693 		heap->finalize_list = next;
50694 	} else {
50695 		DUK_ASSERT(hdr != heap->finalize_list);
50696 		DUK_HEAPHDR_SET_NEXT(heap, prev, next);
50697 	}
50698 #else
50699 	duk_heaphdr *next;
50700 	duk_heaphdr *curr;
50701 
50702 	/* Random removal is expensive: we need to locate the previous element
50703 	 * because we don't have a 'prev' pointer.
50704 	 */
50705 	curr = heap->finalize_list;
50706 	if (curr == hdr) {
50707 		heap->finalize_list = DUK_HEAPHDR_GET_NEXT(heap, curr);
50708 	} else {
50709 		DUK_ASSERT(hdr != heap->finalize_list);
50710 		for (;;) {
50711 			DUK_ASSERT(curr != NULL);  /* Caller responsibility. */
50712 
50713 			next = DUK_HEAPHDR_GET_NEXT(heap, curr);
50714 			if (next == hdr) {
50715 				next = DUK_HEAPHDR_GET_NEXT(heap, hdr);
50716 				DUK_HEAPHDR_SET_NEXT(heap, curr, next);
50717 				break;
50718 			}
50719 		}
50720 	}
50721 #endif
50722 }
50723 #endif  /* DUK_USE_FINALIZER_SUPPORT */
50724 
50725 #if defined(DUK_USE_ASSERTIONS)
50726 DUK_INTERNAL duk_bool_t duk_heap_in_heap_allocated(duk_heap *heap, duk_heaphdr *ptr) {
50727 	duk_heaphdr *curr;
50728 	DUK_ASSERT(heap != NULL);
50729 
50730 	for (curr = heap->heap_allocated; curr != NULL; curr = DUK_HEAPHDR_GET_NEXT(heap, curr)) {
50731 		if (curr == ptr) {
50732 			return 1;
50733 		}
50734 	}
50735 	return 0;
50736 }
50737 #endif  /* DUK_USE_ASSERTIONS */
50738 
50739 #if defined(DUK_USE_INTERRUPT_COUNTER)
50740 DUK_INTERNAL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr) {
50741 	duk_hthread *curr_thr;
50742 
50743 	DUK_ASSERT(heap != NULL);
50744 
50745 	if (new_thr != NULL) {
50746 		curr_thr = heap->curr_thread;
50747 		if (curr_thr == NULL) {
50748 			/* For initial entry use default value; zero forces an
50749 			 * interrupt before executing the first insturction.
50750 			 */
50751 			DUK_DD(DUK_DDPRINT("switch thread, initial entry, init default interrupt counter"));
50752 			new_thr->interrupt_counter = 0;
50753 			new_thr->interrupt_init = 0;
50754 		} else {
50755 			/* Copy interrupt counter/init value state to new thread (if any).
50756 			 * It's OK for new_thr to be the same as curr_thr.
50757 			 */
50758 #if defined(DUK_USE_DEBUG)
50759 			if (new_thr != curr_thr) {
50760 				DUK_DD(DUK_DDPRINT("switch thread, not initial entry, copy interrupt counter"));
50761 			}
50762 #endif
50763 			new_thr->interrupt_counter = curr_thr->interrupt_counter;
50764 			new_thr->interrupt_init = curr_thr->interrupt_init;
50765 		}
50766 	} else {
50767 		DUK_DD(DUK_DDPRINT("switch thread, new thread is NULL, no interrupt counter changes"));
50768 	}
50769 
50770 	heap->curr_thread = new_thr;  /* may be NULL */
50771 }
50772 #endif  /* DUK_USE_INTERRUPT_COUNTER */
50773 #line 1 "duk_heap_refcount.c"
50774 /*
50775  *  Reference counting implementation.
50776  *
50777  *  INCREF/DECREF, finalization and freeing of objects whose refcount reaches
50778  *  zero (refzero).  These operations are very performance sensitive, so
50779  *  various small tricks are used in an attempt to maximize speed.
50780  */
50781 
50782 /* #include duk_internal.h -> already included */
50783 
50784 #if defined(DUK_USE_REFERENCE_COUNTING)
50785 
50786 #if !defined(DUK_USE_DOUBLE_LINKED_HEAP)
50787 #error internal error, reference counting requires a double linked heap
50788 #endif
50789 
50790 /*
50791  *  Heap object refcount finalization.
50792  *
50793  *  When an object is about to be freed, all other objects it refers to must
50794  *  be decref'd.  Refcount finalization does NOT free the object or its inner
50795  *  allocations (mark-and-sweep shares these helpers), it just manipulates
50796  *  the refcounts.
50797  *
50798  *  Note that any of the DECREFs may cause a refcount to drop to zero.  If so,
50799  *  the object won't be refzero processed inline, but will just be queued to
50800  *  refzero_list and processed by an earlier caller working on refzero_list,
50801  *  eliminating C recursion from even long refzero cascades.  If refzero
50802  *  finalization is triggered by mark-and-sweep, refzero conditions are ignored
50803  *  (objects are not even queued to refzero_list) because mark-and-sweep deals
50804  *  with them; refcounts are still updated so that they remain in sync with
50805  *  actual references.
50806  */
50807 
50808 DUK_LOCAL void duk__decref_tvals_norz(duk_hthread *thr, duk_tval *tv, duk_idx_t count) {
50809 	DUK_ASSERT(count == 0 || tv != NULL);
50810 
50811 	while (count-- > 0) {
50812 		DUK_TVAL_DECREF_NORZ(thr, tv);
50813 		tv++;
50814 	}
50815 }
50816 
50817 DUK_INTERNAL void duk_hobject_refcount_finalize_norz(duk_heap *heap, duk_hobject *h) {
50818 	duk_hthread *thr;
50819 	duk_uint_fast32_t i;
50820 	duk_uint_fast32_t n;
50821 	duk_propvalue *p_val;
50822 	duk_tval *p_tv;
50823 	duk_hstring **p_key;
50824 	duk_uint8_t *p_flag;
50825 	duk_hobject *h_proto;
50826 
50827 	DUK_ASSERT(heap != NULL);
50828 	DUK_ASSERT(heap->heap_thread != NULL);
50829 	DUK_ASSERT(h);
50830 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) h) == DUK_HTYPE_OBJECT);
50831 
50832 	thr = heap->heap_thread;
50833 	DUK_ASSERT(thr != NULL);
50834 
50835 	p_key = DUK_HOBJECT_E_GET_KEY_BASE(heap, h);
50836 	p_val = DUK_HOBJECT_E_GET_VALUE_BASE(heap, h);
50837 	p_flag = DUK_HOBJECT_E_GET_FLAGS_BASE(heap, h);
50838 	n = DUK_HOBJECT_GET_ENEXT(h);
50839 	while (n-- > 0) {
50840 		duk_hstring *key;
50841 
50842 		key = p_key[n];
50843 		if (DUK_UNLIKELY(key == NULL)) {
50844 			continue;
50845 		}
50846 		DUK_HSTRING_DECREF_NORZ(thr, key);
50847 		if (DUK_UNLIKELY(p_flag[n] & DUK_PROPDESC_FLAG_ACCESSOR)) {
50848 			duk_hobject *h_getset;
50849 			h_getset = p_val[n].a.get;
50850 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
50851 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
50852 			h_getset = p_val[n].a.set;
50853 			DUK_ASSERT(h_getset == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_getset));
50854 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_getset);
50855 		} else {
50856 			duk_tval *tv_val;
50857 			tv_val = &p_val[n].v;
50858 			DUK_TVAL_DECREF_NORZ(thr, tv_val);
50859 		}
50860 	}
50861 
50862 	p_tv = DUK_HOBJECT_A_GET_BASE(heap, h);
50863 	n = DUK_HOBJECT_GET_ASIZE(h);
50864 	while (n-- > 0) {
50865 		duk_tval *tv_val;
50866 		tv_val = p_tv + n;
50867 		DUK_TVAL_DECREF_NORZ(thr, tv_val);
50868 	}
50869 
50870 	/* Hash part is a 'weak reference' and doesn't contribute to refcounts. */
50871 
50872 	h_proto = (duk_hobject *) DUK_HOBJECT_GET_PROTOTYPE(heap, h);
50873 	DUK_ASSERT(h_proto == NULL || DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_proto));
50874 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, h_proto);
50875 
50876 	/* XXX: Object subclass tests are quite awkward at present, ideally
50877 	 * we should be able to switch-case here with a dense index (subtype
50878 	 * number or something).  For now, fast path plain objects and arrays
50879 	 * and bit test the rest individually.
50880 	 */
50881 
50882 	if (DUK_HOBJECT_HAS_FASTREFS(h)) {
50883 		/* Plain object or array, nothing more to do.  While a
50884 		 * duk_harray has additional fields, none of them need
50885 		 * DECREF updates.
50886 		 */
50887 		DUK_ASSERT(DUK_HOBJECT_ALLOWS_FASTREFS(h));
50888 		return;
50889 	}
50890 	DUK_ASSERT(DUK_HOBJECT_PROHIBITS_FASTREFS(h));
50891 
50892 	/* Slow path: special object, start bit checks from most likely. */
50893 
50894 	/* XXX: reorg, more common first */
50895 	if (DUK_HOBJECT_IS_COMPFUNC(h)) {
50896 		duk_hcompfunc *f = (duk_hcompfunc *) h;
50897 		duk_tval *tv, *tv_end;
50898 		duk_hobject **funcs, **funcs_end;
50899 
50900 		DUK_ASSERT_HCOMPFUNC_VALID(f);
50901 
50902 		if (DUK_LIKELY(DUK_HCOMPFUNC_GET_DATA(heap, f) != NULL)) {
50903 			tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(heap, f);
50904 			tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(heap, f);
50905 			while (tv < tv_end) {
50906 				DUK_TVAL_DECREF_NORZ(thr, tv);
50907 				tv++;
50908 			}
50909 
50910 			funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(heap, f);
50911 			funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(heap, f);
50912 			while (funcs < funcs_end) {
50913 				duk_hobject *h_func;
50914 				h_func = *funcs;
50915 				DUK_ASSERT(h_func != NULL);
50916 				DUK_ASSERT(DUK_HEAPHDR_IS_OBJECT((duk_heaphdr *) h_func));
50917 				DUK_HCOMPFUNC_DECREF_NORZ(thr, (duk_hcompfunc *) h_func);
50918 				funcs++;
50919 			}
50920 		} else {
50921 			/* May happen in some out-of-memory corner cases. */
50922 			DUK_D(DUK_DPRINT("duk_hcompfunc 'data' is NULL, skipping decref"));
50923 		}
50924 
50925 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_LEXENV(heap, f));
50926 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_heaphdr *) DUK_HCOMPFUNC_GET_VARENV(heap, f));
50927 		DUK_HEAPHDR_DECREF_ALLOWNULL(thr, (duk_hbuffer *) DUK_HCOMPFUNC_GET_DATA(heap, f));
50928 	} else if (DUK_HOBJECT_IS_DECENV(h)) {
50929 		duk_hdecenv *e = (duk_hdecenv *) h;
50930 		DUK_ASSERT_HDECENV_VALID(e);
50931 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, e->thread);
50932 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, e->varmap);
50933 	} else if (DUK_HOBJECT_IS_OBJENV(h)) {
50934 		duk_hobjenv *e = (duk_hobjenv *) h;
50935 		DUK_ASSERT_HOBJENV_VALID(e);
50936 		DUK_ASSERT(e->target != NULL);  /* Required for object environments. */
50937 		DUK_HOBJECT_DECREF_NORZ(thr, e->target);
50938 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
50939 	} else if (DUK_HOBJECT_IS_BUFOBJ(h)) {
50940 		duk_hbufobj *b = (duk_hbufobj *) h;
50941 		DUK_ASSERT_HBUFOBJ_VALID(b);
50942 		DUK_HBUFFER_DECREF_NORZ_ALLOWNULL(thr, (duk_hbuffer *) b->buf);
50943 		DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) b->buf_prop);
50944 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
50945 	} else if (DUK_HOBJECT_IS_BOUNDFUNC(h)) {
50946 		duk_hboundfunc *f = (duk_hboundfunc *) (void *) h;
50947 		DUK_ASSERT_HBOUNDFUNC_VALID(f);
50948 		DUK_TVAL_DECREF_NORZ(thr, &f->target);
50949 		DUK_TVAL_DECREF_NORZ(thr, &f->this_binding);
50950 		duk__decref_tvals_norz(thr, f->args, f->nargs);
50951 #if defined(DUK_USE_ES6_PROXY)
50952 	} else if (DUK_HOBJECT_IS_PROXY(h)) {
50953 		duk_hproxy *p = (duk_hproxy *) h;
50954 		DUK_ASSERT_HPROXY_VALID(p);
50955 		DUK_HOBJECT_DECREF_NORZ(thr, p->target);
50956 		DUK_HOBJECT_DECREF_NORZ(thr, p->handler);
50957 #endif  /* DUK_USE_ES6_PROXY */
50958 	} else if (DUK_HOBJECT_IS_THREAD(h)) {
50959 		duk_hthread *t = (duk_hthread *) h;
50960 		duk_activation *act;
50961 		duk_tval *tv;
50962 
50963 		DUK_ASSERT_HTHREAD_VALID(t);
50964 
50965 		tv = t->valstack;
50966 		while (tv < t->valstack_top) {
50967 			DUK_TVAL_DECREF_NORZ(thr, tv);
50968 			tv++;
50969 		}
50970 
50971 		for (act = t->callstack_curr; act != NULL; act = act->parent) {
50972 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) DUK_ACT_GET_FUNC(act));
50973 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->var_env);
50974 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->lex_env);
50975 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
50976 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) act->prev_caller);
50977 #endif
50978 #if 0  /* nothing now */
50979 			for (cat = act->cat; cat != NULL; cat = cat->parent) {
50980 			}
50981 #endif
50982 		}
50983 
50984 
50985 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
50986 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, (duk_hobject *) t->builtins[i]);
50987 		}
50988 
50989 		DUK_HTHREAD_DECREF_NORZ_ALLOWNULL(thr, (duk_hthread *) t->resumer);
50990 	} else {
50991 		/* We may come here if the object should have a FASTREFS flag
50992 		 * but it's missing for some reason.  Assert for never getting
50993 		 * here; however, other than performance, this is harmless.
50994 		 */
50995 		DUK_D(DUK_DPRINT("missing FASTREFS flag for: %!iO", h));
50996 		DUK_ASSERT(0);
50997 	}
50998 }
50999 
51000 DUK_INTERNAL void duk_heaphdr_refcount_finalize_norz(duk_heap *heap, duk_heaphdr *hdr) {
51001 	DUK_ASSERT(heap != NULL);
51002 	DUK_ASSERT(heap->heap_thread != NULL);
51003 	DUK_ASSERT(hdr != NULL);
51004 
51005 	if (DUK_HEAPHDR_IS_OBJECT(hdr)) {
51006 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) hdr);
51007 	}
51008 	/* DUK_HTYPE_BUFFER: nothing to finalize */
51009 	/* DUK_HTYPE_STRING: nothing to finalize */
51010 }
51011 
51012 /*
51013  *  Refzero processing for duk_hobject: queue a refzero'ed object to either
51014  *  finalize_list or refzero_list and process the relevent list(s) if
51015  *  necessary.
51016  *
51017  *  Refzero_list is single linked, with only 'prev' pointers set and valid.
51018  *  All 'next' pointers are intentionally left as garbage.  This doesn't
51019  *  matter because refzero_list is processed to completion before any other
51020  *  code (like mark-and-sweep) might walk the list.
51021  *
51022  *  In more detail:
51023  *
51024  *  - On first insert refzero_list is NULL and the new object becomes the
51025  *    first and only element on the list; duk__refcount_free_pending() is
51026  *    called and it starts processing the list from the initial element,
51027  *    i.e. the list tail.
51028  *
51029  *  - As each object is refcount finalized, new objects may be queued to
51030  *    refzero_list head.  Their 'next' pointers are left as garbage, but
51031  *    'prev' points are set correctly, with the element at refzero_list
51032  *    having a NULL 'prev' pointer.  The fact that refzero_list is non-NULL
51033  *    is used to reject (1) recursive duk__refcount_free_pending() and
51034  *    (2) finalize_list processing calls.
51035  *
51036  *  - When we're done with the current object, read its 'prev' pointer and
51037  *    free the object.  If 'prev' is NULL, we've reached head of list and are
51038  *    done: set refzero_list to NULL and process pending finalizers.  Otherwise
51039  *    continue processing the list.
51040  *
51041  *  A refzero cascade is free of side effects because it only involves
51042  *  queueing more objects and freeing memory; finalizer execution is blocked
51043  *  in the code path queueing objects to finalize_list.  As a result the
51044  *  initial refzero call (which triggers duk__refcount_free_pending()) must
51045  *  check finalize_list so that finalizers are executed snappily.
51046  *
51047  *  If finalize_list processing starts first, refzero may occur while we're
51048  *  processing finalizers.  That's fine: that particular refzero cascade is
51049  *  handled to completion without side effects.  Once the cascade is complete,
51050  *  we'll run pending finalizers but notice that we're already doing that and
51051  *  return.
51052  *
51053  *  This could be expanded to allow incremental freeing: just bail out
51054  *  early and resume at a future alloc/decref/refzero.  However, if that
51055  *  were done, the list structure would need to be kept consistent at all
51056  *  times, mark-and-sweep would need to handle refzero_list, etc.
51057  */
51058 
51059 DUK_LOCAL void duk__refcount_free_pending(duk_heap *heap) {
51060 	duk_heaphdr *curr;
51061 #if defined(DUK_USE_DEBUG)
51062 	duk_int_t count = 0;
51063 #endif
51064 
51065 	DUK_ASSERT(heap != NULL);
51066 
51067 	curr = heap->refzero_list;
51068 	DUK_ASSERT(curr != NULL);
51069 	DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, curr) == NULL);  /* We're called on initial insert only. */
51070 	/* curr->next is GARBAGE. */
51071 
51072 	do {
51073 		duk_heaphdr *prev;
51074 
51075 		DUK_DDD(DUK_DDDPRINT("refzero processing %p: %!O", (void *) curr, (duk_heaphdr *) curr));
51076 
51077 #if defined(DUK_USE_DEBUG)
51078 		count++;
51079 #endif
51080 
51081 		DUK_ASSERT(curr != NULL);
51082 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(curr) == DUK_HTYPE_OBJECT);  /* currently, always the case */
51083 		/* FINALIZED may be set; don't care about flags here. */
51084 
51085 		/* Refcount finalize 'curr'.  Refzero_list must be non-NULL
51086 		 * here to prevent recursive entry to duk__refcount_free_pending().
51087 		 */
51088 		DUK_ASSERT(heap->refzero_list != NULL);
51089 		duk_hobject_refcount_finalize_norz(heap, (duk_hobject *) curr);
51090 
51091 		prev = DUK_HEAPHDR_GET_PREV(heap, curr);
51092 		DUK_ASSERT((prev == NULL && heap->refzero_list == curr) || \
51093 		           (prev != NULL && heap->refzero_list != curr));
51094 		/* prev->next is intentionally not updated and is garbage. */
51095 
51096 		duk_free_hobject(heap, (duk_hobject *) curr);  /* Invalidates 'curr'. */
51097 
51098 		curr = prev;
51099 	} while (curr != NULL);
51100 
51101 	heap->refzero_list = NULL;
51102 
51103 	DUK_DD(DUK_DDPRINT("refzero processed %ld objects", (long) count));
51104 }
51105 
51106 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hobject(duk_heap *heap, duk_hobject *obj, duk_bool_t skip_free_pending) {
51107 	duk_heaphdr *hdr;
51108 	duk_heaphdr *root;
51109 
51110 	DUK_ASSERT(heap != NULL);
51111 	DUK_ASSERT(heap->heap_thread != NULL);
51112 	DUK_ASSERT(obj != NULL);
51113 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) obj) == DUK_HTYPE_OBJECT);
51114 
51115 	hdr = (duk_heaphdr *) obj;
51116 
51117 	/* Refzero'd objects must be in heap_allocated.  They can't be in
51118 	 * finalize_list because all objects on finalize_list have an
51119 	 * artificial +1 refcount bump.
51120 	 */
51121 #if defined(DUK_USE_ASSERTIONS)
51122 	DUK_ASSERT(duk_heap_in_heap_allocated(heap, (duk_heaphdr *) obj));
51123 #endif
51124 
51125 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, hdr);
51126 
51127 #if defined(DUK_USE_FINALIZER_SUPPORT)
51128 	/* This finalizer check MUST BE side effect free.  It should also be
51129 	 * as fast as possible because it's applied to every object freed.
51130 	 */
51131 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_FINALIZER_FAST(heap, (duk_hobject *) hdr) != 0U)) {
51132 		/* Special case: FINALIZED may be set if mark-and-sweep queued
51133 		 * object for finalization, the finalizer was executed (and
51134 		 * FINALIZED set), mark-and-sweep hasn't yet processed the
51135 		 * object again, but its refcount drops to zero.  Free without
51136 		 * running the finalizer again.
51137 		 */
51138 		if (DUK_HEAPHDR_HAS_FINALIZED(hdr)) {
51139 			DUK_D(DUK_DPRINT("refzero'd object has finalizer and FINALIZED is set -> free"));
51140 		} else {
51141 			/* Set FINALIZABLE flag so that all objects on finalize_list
51142 			 * will have it set and are thus detectable based on the
51143 			 * flag alone.
51144 			 */
51145 			DUK_HEAPHDR_SET_FINALIZABLE(hdr);
51146 			DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
51147 
51148 #if defined(DUK_USE_REFERENCE_COUNTING)
51149 			/* Bump refcount on finalize_list insert so that a
51150 			 * refzero can never occur when an object is waiting
51151 			 * for its finalizer call.  Refzero might otherwise
51152 			 * now happen because we allow duk_push_heapptr() for
51153 			 * objects pending finalization.
51154 			 */
51155 			DUK_HEAPHDR_PREINC_REFCOUNT(hdr);
51156 #endif
51157 			DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap, hdr);
51158 
51159 			/* Process finalizers unless skipping is explicitly
51160 			 * requested (NORZ) or refzero_list is being processed
51161 			 * (avoids side effects during a refzero cascade).
51162 			 * If refzero_list is processed, the initial refzero
51163 			 * call will run pending finalizers when refzero_list
51164 			 * is done.
51165 			 */
51166 			if (!skip_free_pending && heap->refzero_list == NULL) {
51167 				duk_heap_process_finalize_list(heap);
51168 			}
51169 			return;
51170 		}
51171 	}
51172 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51173 
51174 	/* No need to finalize, free object via refzero_list. */
51175 
51176 	root = heap->refzero_list;
51177 
51178 	DUK_HEAPHDR_SET_PREV(heap, hdr, NULL);
51179 	/* 'next' is left as GARBAGE. */
51180 	heap->refzero_list = hdr;
51181 
51182 	if (root == NULL) {
51183 		/* Object is now queued.  Refzero_list was NULL so
51184 		 * no-one is currently processing it; do it here.
51185 		 * With refzero processing just doing a cascade of
51186 		 * free calls, we can process it directly even when
51187 		 * NORZ macros are used: there are no side effects.
51188 		 */
51189 		duk__refcount_free_pending(heap);
51190 		DUK_ASSERT(heap->refzero_list == NULL);
51191 
51192 		/* Process finalizers only after the entire cascade
51193 		 * is finished.  In most cases there's nothing to
51194 		 * finalize, so fast path check to avoid a call.
51195 		 */
51196 #if defined(DUK_USE_FINALIZER_SUPPORT)
51197 		if (!skip_free_pending && DUK_UNLIKELY(heap->finalize_list != NULL)) {
51198 			duk_heap_process_finalize_list(heap);
51199 		}
51200 #endif
51201 	} else {
51202 		DUK_ASSERT(DUK_HEAPHDR_GET_PREV(heap, root) == NULL);
51203 		DUK_HEAPHDR_SET_PREV(heap, root, hdr);
51204 
51205 		/* Object is now queued.  Because refzero_list was
51206 		 * non-NULL, it's already being processed by someone
51207 		 * in the C call stack, so we're done.
51208 		 */
51209 	}
51210 }
51211 
51212 #if defined(DUK_USE_FINALIZER_SUPPORT)
51213 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_refzero_check_fast(duk_hthread *thr) {
51214 	DUK_ASSERT(thr != NULL);
51215 	DUK_ASSERT(thr->heap != NULL);
51216 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51217 
51218 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51219 		duk_heap_process_finalize_list(thr->heap);
51220 	}
51221 }
51222 
51223 DUK_INTERNAL void duk_refzero_check_slow(duk_hthread *thr) {
51224 	DUK_ASSERT(thr != NULL);
51225 	DUK_ASSERT(thr->heap != NULL);
51226 	DUK_ASSERT(thr->heap->refzero_list == NULL);  /* Processed to completion inline. */
51227 
51228 	if (DUK_UNLIKELY(thr->heap->finalize_list != NULL)) {
51229 		duk_heap_process_finalize_list(thr->heap);
51230 	}
51231 }
51232 #endif  /* DUK_USE_FINALIZER_SUPPORT */
51233 
51234 /*
51235  *  Refzero processing for duk_hstring.
51236  */
51237 
51238 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hstring(duk_heap *heap, duk_hstring *str) {
51239 	DUK_ASSERT(heap != NULL);
51240 	DUK_ASSERT(heap->heap_thread != NULL);
51241 	DUK_ASSERT(str != NULL);
51242 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) str) == DUK_HTYPE_STRING);
51243 
51244 	duk_heap_strcache_string_remove(heap, str);
51245 	duk_heap_strtable_unlink(heap, str);
51246 	duk_free_hstring(heap, str);
51247 }
51248 
51249 /*
51250  *  Refzero processing for duk_hbuffer.
51251  */
51252 
51253 DUK_LOCAL DUK_INLINE void duk__refcount_refzero_hbuffer(duk_heap *heap, duk_hbuffer *buf) {
51254 	DUK_ASSERT(heap != NULL);
51255 	DUK_ASSERT(heap->heap_thread != NULL);
51256 	DUK_ASSERT(buf != NULL);
51257 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE((duk_heaphdr *) buf) == DUK_HTYPE_BUFFER);
51258 
51259 	DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap, (duk_heaphdr *) buf);
51260 	duk_free_hbuffer(heap, buf);
51261 }
51262 
51263 /*
51264  *  Incref and decref functions.
51265  *
51266  *  Decref may trigger immediate refzero handling, which may free and finalize
51267  *  an arbitrary number of objects (a "DECREF cascade").
51268  *
51269  *  Refzero handling is skipped entirely if (1) mark-and-sweep is running or
51270  *  (2) execution is paused in the debugger.  The objects are left in the heap,
51271  *  and will be freed by mark-and-sweep or eventual heap destruction.
51272  *
51273  *  This is necessary during mark-and-sweep because refcounts are also updated
51274  *  during the sweep phase (otherwise objects referenced by a swept object
51275  *  would have incorrect refcounts) which then calls here.  This could be
51276  *  avoided by using separate decref macros in mark-and-sweep; however,
51277  *  mark-and-sweep also calls finalizers which would use the ordinary decref
51278  *  macros anyway.
51279  *
51280  *  We can't process refzeros (= free objects) when the debugger is running
51281  *  as the debugger might make an object unreachable but still continue
51282  *  inspecting it (or even cause it to be pushed back).  So we must rely on
51283  *  mark-and-sweep to collect them.
51284  *
51285  *  The DUK__RZ_SUPPRESS_CHECK() condition is also used in heap destruction
51286  *  when running finalizers for remaining objects: the flag prevents objects
51287  *  from being moved around in heap linked lists while that's being done.
51288  *
51289  *  The suppress condition is important to performance.
51290  */
51291 
51292 #define DUK__RZ_SUPPRESS_ASSERT1() do { \
51293 		DUK_ASSERT(thr != NULL); \
51294 		DUK_ASSERT(thr->heap != NULL); \
51295 		/* When mark-and-sweep runs, heap_thread must exist. */ \
51296 		DUK_ASSERT(thr->heap->ms_running == 0 || thr->heap->heap_thread != NULL); \
51297 		/* When mark-and-sweep runs, the 'thr' argument always matches heap_thread. \
51298 		 * This could be used to e.g. suppress check against 'thr' directly (and \
51299 		 * knowing it would be heap_thread); not really used now. \
51300 		 */ \
51301 		DUK_ASSERT(thr->heap->ms_running == 0 || thr == thr->heap->heap_thread); \
51302 		/* We may be called when the heap is initializing and we process \
51303 		 * refzeros normally, but mark-and-sweep and finalizers are prevented \
51304 		 * if that's the case. \
51305 		 */ \
51306 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->ms_prevent_count > 0); \
51307 		DUK_ASSERT(thr->heap->heap_initializing == 0 || thr->heap->pf_prevent_count > 0); \
51308 	} while (0)
51309 
51310 #if defined(DUK_USE_DEBUGGER_SUPPORT)
51311 #define DUK__RZ_SUPPRESS_ASSERT2() do { \
51312 		/* When debugger is paused, ms_running is set. */ \
51313 		DUK_ASSERT(!DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->ms_running != 0); \
51314 	} while (0)
51315 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51316 #else
51317 #define DUK__RZ_SUPPRESS_ASSERT2() do { } while (0)
51318 #define DUK__RZ_SUPPRESS_COND()  (heap->ms_running != 0)
51319 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
51320 
51321 #define DUK__RZ_SUPPRESS_CHECK() do { \
51322 		DUK__RZ_SUPPRESS_ASSERT1(); \
51323 		DUK__RZ_SUPPRESS_ASSERT2(); \
51324 		if (DUK_UNLIKELY(DUK__RZ_SUPPRESS_COND())) { \
51325 			DUK_DDD(DUK_DDDPRINT("refzero handling suppressed (not even queued) when mark-and-sweep running, object: %p", (void *) h)); \
51326 			return; \
51327 		} \
51328 	} while (0)
51329 
51330 #define DUK__RZ_STRING() do { \
51331 		duk__refcount_refzero_hstring(heap, (duk_hstring *) h); \
51332 	} while (0)
51333 #define DUK__RZ_BUFFER() do { \
51334 		duk__refcount_refzero_hbuffer(heap, (duk_hbuffer *) h); \
51335 	} while (0)
51336 #define DUK__RZ_OBJECT() do { \
51337 		duk__refcount_refzero_hobject(heap, (duk_hobject *) h, skip_free_pending); \
51338 	} while (0)
51339 
51340 /* XXX: test the effect of inlining here vs. NOINLINE in refzero helpers */
51341 #if defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51342 #define DUK__RZ_INLINE DUK_ALWAYS_INLINE
51343 #else
51344 #define DUK__RZ_INLINE /*nop*/
51345 #endif
51346 
51347 DUK_LOCAL DUK__RZ_INLINE void duk__hstring_refzero_helper(duk_hthread *thr, duk_hstring *h) {
51348 	duk_heap *heap;
51349 
51350 	DUK_ASSERT(thr != NULL);
51351 	DUK_ASSERT(h != NULL);
51352 	heap = thr->heap;
51353 
51354 	DUK__RZ_SUPPRESS_CHECK();
51355 	DUK__RZ_STRING();
51356 }
51357 
51358 DUK_LOCAL DUK__RZ_INLINE void duk__hbuffer_refzero_helper(duk_hthread *thr, duk_hbuffer *h) {
51359 	duk_heap *heap;
51360 
51361 	DUK_ASSERT(thr != NULL);
51362 	DUK_ASSERT(h != NULL);
51363 	heap = thr->heap;
51364 
51365 	DUK__RZ_SUPPRESS_CHECK();
51366 	DUK__RZ_BUFFER();
51367 }
51368 
51369 DUK_LOCAL DUK__RZ_INLINE void duk__hobject_refzero_helper(duk_hthread *thr, duk_hobject *h, duk_bool_t skip_free_pending) {
51370 	duk_heap *heap;
51371 
51372 	DUK_ASSERT(thr != NULL);
51373 	DUK_ASSERT(h != NULL);
51374 	heap = thr->heap;
51375 
51376 	DUK__RZ_SUPPRESS_CHECK();
51377 	DUK__RZ_OBJECT();
51378 }
51379 
51380 DUK_LOCAL DUK__RZ_INLINE void duk__heaphdr_refzero_helper(duk_hthread *thr, duk_heaphdr *h, duk_bool_t skip_free_pending) {
51381 	duk_heap *heap;
51382 	duk_small_uint_t htype;
51383 
51384 	DUK_ASSERT(thr != NULL);
51385 	DUK_ASSERT(h != NULL);
51386 	heap = thr->heap;
51387 
51388 	htype = (duk_small_uint_t) DUK_HEAPHDR_GET_TYPE(h);
51389 	DUK__RZ_SUPPRESS_CHECK();
51390 
51391 	switch (htype) {
51392 	case DUK_HTYPE_STRING:
51393 		/* Strings have no internal references but do have "weak"
51394 		 * references in the string cache.  Also note that strings
51395 		 * are not on the heap_allocated list like other heap
51396 		 * elements.
51397 		 */
51398 
51399 		DUK__RZ_STRING();
51400 		break;
51401 
51402 	case DUK_HTYPE_OBJECT:
51403 		/* Objects have internal references.  Must finalize through
51404 		 * the "refzero" work list.
51405 		 */
51406 
51407 		DUK__RZ_OBJECT();
51408 		break;
51409 
51410 	default:
51411 		/* Buffers have no internal references.  However, a dynamic
51412 		 * buffer has a separate allocation for the buffer.  This is
51413 		 * freed by duk_heap_free_heaphdr_raw().
51414 		 */
51415 
51416 		DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_BUFFER);
51417 		DUK__RZ_BUFFER();
51418 		break;
51419 	}
51420 }
51421 
51422 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h) {
51423 	duk__heaphdr_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51424 }
51425 
51426 DUK_INTERNAL DUK_NOINLINE void duk_heaphdr_refzero_norz(duk_hthread *thr, duk_heaphdr *h) {
51427 	duk__heaphdr_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51428 }
51429 
51430 DUK_INTERNAL DUK_NOINLINE void duk_hstring_refzero(duk_hthread *thr, duk_hstring *h) {
51431 	duk__hstring_refzero_helper(thr, h);
51432 }
51433 
51434 DUK_INTERNAL DUK_NOINLINE void duk_hbuffer_refzero(duk_hthread *thr, duk_hbuffer *h) {
51435 	duk__hbuffer_refzero_helper(thr, h);
51436 }
51437 
51438 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero(duk_hthread *thr, duk_hobject *h) {
51439 	duk__hobject_refzero_helper(thr, h, 0 /*skip_free_pending*/);
51440 }
51441 
51442 DUK_INTERNAL DUK_NOINLINE void duk_hobject_refzero_norz(duk_hthread *thr, duk_hobject *h) {
51443 	duk__hobject_refzero_helper(thr, h, 1 /*skip_free_pending*/);
51444 }
51445 
51446 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51447 DUK_INTERNAL void duk_tval_incref(duk_tval *tv) {
51448 	DUK_ASSERT(tv != NULL);
51449 
51450 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51451 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51452 		DUK_ASSERT(h != NULL);
51453 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51454 		DUK_ASSERT_DISABLE(h->h_refcount >= 0);
51455 		DUK_HEAPHDR_PREINC_REFCOUNT(h);
51456 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) != 0);  /* No wrapping. */
51457 	}
51458 }
51459 
51460 DUK_INTERNAL void duk_tval_decref(duk_hthread *thr, duk_tval *tv) {
51461 	DUK_ASSERT(thr != NULL);
51462 	DUK_ASSERT(tv != NULL);
51463 
51464 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51465 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51466 		DUK_ASSERT(h != NULL);
51467 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51468 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51469 #if 0
51470 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51471 			return;
51472 		}
51473 		duk_heaphdr_refzero(thr, h);
51474 #else
51475 		duk_heaphdr_decref(thr, h);
51476 #endif
51477 	}
51478 }
51479 
51480 DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
51481 	DUK_ASSERT(thr != NULL);
51482 	DUK_ASSERT(tv != NULL);
51483 
51484 	if (DUK_TVAL_NEEDS_REFCOUNT_UPDATE(tv)) {
51485 		duk_heaphdr *h = DUK_TVAL_GET_HEAPHDR(tv);
51486 		DUK_ASSERT(h != NULL);
51487 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51488 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT(h) >= 1);
51489 #if 0
51490 		if (DUK_HEAPHDR_PREDEC_REFCOUNT(h) != 0) {
51491 			return;
51492 		}
51493 		duk_heaphdr_refzero_norz(thr, h);
51494 #else
51495 		duk_heaphdr_decref_norz(thr, h);
51496 #endif
51497 	}
51498 }
51499 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51500 
51501 #define DUK__DECREF_ASSERTS() do { \
51502 		DUK_ASSERT(thr != NULL); \
51503 		DUK_ASSERT(thr->heap != NULL); \
51504 		DUK_ASSERT(h != NULL); \
51505 		DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID((duk_heaphdr *) h)); \
51506 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
51507 	} while (0)
51508 #if defined(DUK_USE_ROM_OBJECTS)
51509 #define DUK__INCREF_SHARED() do { \
51510 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51511 			return; \
51512 		} \
51513 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51514 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51515 	} while (0)
51516 #define DUK__DECREF_SHARED() do { \
51517 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
51518 			return; \
51519 		} \
51520 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51521 			return; \
51522 		} \
51523 	} while (0)
51524 #else
51525 #define DUK__INCREF_SHARED() do { \
51526 		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
51527 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) != 0);  /* No wrapping. */ \
51528 	} while (0)
51529 #define DUK__DECREF_SHARED() do { \
51530 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
51531 			return; \
51532 		} \
51533 	} while (0)
51534 #endif
51535 
51536 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT)
51537 /* This will in practice be inlined because it's just an INC instructions
51538  * and a bit test + INC when ROM objects are enabled.
51539  */
51540 DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
51541 	DUK_ASSERT(h != NULL);
51542 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
51543 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
51544 
51545 	DUK__INCREF_SHARED();
51546 }
51547 
51548 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
51549 	DUK__DECREF_ASSERTS();
51550 	DUK__DECREF_SHARED();
51551 	duk_heaphdr_refzero(thr, h);
51552 
51553 	/* Forced mark-and-sweep when GC torture enabled; this could happen
51554 	 * on any DECREF (but not DECREF_NORZ).
51555 	 */
51556 	DUK_GC_TORTURE(thr->heap);
51557 }
51558 DUK_INTERNAL void duk_heaphdr_decref_norz(duk_hthread *thr, duk_heaphdr *h) {
51559 	DUK__DECREF_ASSERTS();
51560 	DUK__DECREF_SHARED();
51561 	duk_heaphdr_refzero_norz(thr, h);
51562 }
51563 #endif  /* !DUK_USE_FAST_REFCOUNT_DEFAULT */
51564 
51565 #if 0  /* Not needed. */
51566 DUK_INTERNAL void duk_hstring_decref(duk_hthread *thr, duk_hstring *h) {
51567 	DUK__DECREF_ASSERTS();
51568 	DUK__DECREF_SHARED();
51569 	duk_hstring_refzero(thr, h);
51570 }
51571 DUK_INTERNAL void duk_hstring_decref_norz(duk_hthread *thr, duk_hstring *h) {
51572 	DUK__DECREF_ASSERTS();
51573 	DUK__DECREF_SHARED();
51574 	duk_hstring_refzero_norz(thr, h);
51575 }
51576 DUK_INTERNAL void duk_hbuffer_decref(duk_hthread *thr, duk_hbuffer *h) {
51577 	DUK__DECREF_ASSERTS();
51578 	DUK__DECREF_SHARED();
51579 	duk_hbuffer_refzero(thr, h);
51580 }
51581 DUK_INTERNAL void duk_hbuffer_decref_norz(duk_hthread *thr, duk_hbuffer *h) {
51582 	DUK__DECREF_ASSERTS();
51583 	DUK__DECREF_SHARED();
51584 	duk_hbuffer_refzero_norz(thr, h);
51585 }
51586 DUK_INTERNAL void duk_hobject_decref(duk_hthread *thr, duk_hobject *h) {
51587 	DUK__DECREF_ASSERTS();
51588 	DUK__DECREF_SHARED();
51589 	duk_hobject_refzero(thr, h);
51590 }
51591 DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
51592 	DUK__DECREF_ASSERTS();
51593 	DUK__DECREF_SHARED();
51594 	duk_hobject_refzero_norz(thr, h);
51595 }
51596 #endif
51597 
51598 #else  /* DUK_USE_REFERENCE_COUNTING */
51599 
51600 /* no refcounting */
51601 
51602 #endif  /* DUK_USE_REFERENCE_COUNTING */
51603 
51604 /* automatic undefs */
51605 #undef DUK__DECREF_ASSERTS
51606 #undef DUK__DECREF_SHARED
51607 #undef DUK__INCREF_SHARED
51608 #undef DUK__RZ_BUFFER
51609 #undef DUK__RZ_INLINE
51610 #undef DUK__RZ_OBJECT
51611 #undef DUK__RZ_STRING
51612 #undef DUK__RZ_SUPPRESS_ASSERT1
51613 #undef DUK__RZ_SUPPRESS_ASSERT2
51614 #undef DUK__RZ_SUPPRESS_CHECK
51615 #undef DUK__RZ_SUPPRESS_COND
51616 #line 1 "duk_heap_stringcache.c"
51617 /*
51618  *  String cache.
51619  *
51620  *  Provides a cache to optimize indexed string lookups.  The cache keeps
51621  *  track of (byte offset, char offset) states for a fixed number of strings.
51622  *  Otherwise we'd need to scan from either end of the string, as we store
51623  *  strings in (extended) UTF-8.
51624  */
51625 
51626 /* #include duk_internal.h -> already included */
51627 
51628 /*
51629  *  Delete references to given hstring from the heap string cache.
51630  *
51631  *  String cache references are 'weak': they are not counted towards
51632  *  reference counts, nor serve as roots for mark-and-sweep.  When an
51633  *  object is about to be freed, such references need to be removed.
51634  */
51635 
51636 DUK_INTERNAL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h) {
51637 	duk_uint_t i;
51638 	for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51639 		duk_strcache_entry *c = heap->strcache + i;
51640 		if (c->h == h) {
51641 			DUK_DD(DUK_DDPRINT("deleting weak strcache reference to hstring %p from heap %p",
51642 			                   (void *) h, (void *) heap));
51643 			c->h = NULL;
51644 
51645 			/* XXX: the string shouldn't appear twice, but we now loop to the
51646 			 * end anyway; if fixed, add a looping assertion to ensure there
51647 			 * is no duplicate.
51648 			 */
51649 		}
51650 	}
51651 }
51652 
51653 /*
51654  *  String scanning helpers
51655  *
51656  *  All bytes other than UTF-8 continuation bytes ([0x80,0xbf]) are
51657  *  considered to contribute a character.  This must match how string
51658  *  character length is computed.
51659  */
51660 
51661 DUK_LOCAL const duk_uint8_t *duk__scan_forwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51662 	while (n > 0) {
51663 		for (;;) {
51664 			p++;
51665 			if (p >= q) {
51666 				return NULL;
51667 			}
51668 			if ((*p & 0xc0) != 0x80) {
51669 				break;
51670 			}
51671 		}
51672 		n--;
51673 	}
51674 	return p;
51675 }
51676 
51677 DUK_LOCAL const duk_uint8_t *duk__scan_backwards(const duk_uint8_t *p, const duk_uint8_t *q, duk_uint_fast32_t n) {
51678 	while (n > 0) {
51679 		for (;;) {
51680 			p--;
51681 			if (p < q) {
51682 				return NULL;
51683 			}
51684 			if ((*p & 0xc0) != 0x80) {
51685 				break;
51686 			}
51687 		}
51688 		n--;
51689 	}
51690 	return p;
51691 }
51692 
51693 /*
51694  *  Convert char offset to byte offset
51695  *
51696  *  Avoid using the string cache if possible: for ASCII strings byte and
51697  *  char offsets are equal and for short strings direct scanning may be
51698  *  better than using the string cache (which may evict a more important
51699  *  entry).
51700  *
51701  *  Typing now assumes 32-bit string byte/char offsets (duk_uint_fast32_t).
51702  *  Better typing might be to use duk_size_t.
51703  *
51704  *  Caller should ensure 'char_offset' is within the string bounds [0,charlen]
51705  *  (endpoint is inclusive).  If this is not the case, no memory unsafe
51706  *  behavior will happen but an error will be thrown.
51707  */
51708 
51709 DUK_INTERNAL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset) {
51710 	duk_heap *heap;
51711 	duk_strcache_entry *sce;
51712 	duk_uint_fast32_t byte_offset;
51713 	duk_uint_t i;
51714 	duk_bool_t use_cache;
51715 	duk_uint_fast32_t dist_start, dist_end, dist_sce;
51716 	duk_uint_fast32_t char_length;
51717 	const duk_uint8_t *p_start;
51718 	const duk_uint8_t *p_end;
51719 	const duk_uint8_t *p_found;
51720 
51721 	/*
51722 	 *  For ASCII strings, the answer is simple.
51723 	 */
51724 
51725 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51726 		return char_offset;
51727 	}
51728 
51729 	char_length = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h);
51730 	DUK_ASSERT(char_offset <= char_length);
51731 
51732 	if (DUK_LIKELY(DUK_HSTRING_IS_ASCII(h))) {
51733 		/* Must recheck because the 'is ascii' flag may be set
51734 		 * lazily.  Alternatively, we could just compare charlen
51735 		 * to bytelen.
51736 		 */
51737 		return char_offset;
51738 	}
51739 
51740 	/*
51741 	 *  For non-ASCII strings, we need to scan forwards or backwards
51742 	 *  from some starting point.  The starting point may be the start
51743 	 *  or end of the string, or some cached midpoint in the string
51744 	 *  cache.
51745 	 *
51746 	 *  For "short" strings we simply scan without checking or updating
51747 	 *  the cache.  For longer strings we check and update the cache as
51748 	 *  necessary, inserting a new cache entry if none exists.
51749 	 */
51750 
51751 	DUK_DDD(DUK_DDDPRINT("non-ascii string %p, char_offset=%ld, clen=%ld, blen=%ld",
51752 	                     (void *) h, (long) char_offset,
51753 	                     (long) DUK_HSTRING_GET_CHARLEN(h),
51754 	                     (long) DUK_HSTRING_GET_BYTELEN(h)));
51755 
51756 	heap = thr->heap;
51757 	sce = NULL;
51758 	use_cache = (char_length > DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT);
51759 
51760 	if (use_cache) {
51761 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
51762 		DUK_DDD(DUK_DDDPRINT("stringcache before char2byte (using cache):"));
51763 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51764 			duk_strcache_entry *c = heap->strcache + i;
51765 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
51766 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
51767 		}
51768 #endif
51769 
51770 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51771 			duk_strcache_entry *c = heap->strcache + i;
51772 
51773 			if (c->h == h) {
51774 				sce = c;
51775 				break;
51776 			}
51777 		}
51778 	}
51779 
51780 	/*
51781 	 *  Scan from shortest distance:
51782 	 *    - start of string
51783 	 *    - end of string
51784 	 *    - cache entry (if exists)
51785 	 */
51786 
51787 	DUK_ASSERT(DUK_HSTRING_GET_CHARLEN(h) >= char_offset);
51788 	dist_start = char_offset;
51789 	dist_end = char_length - char_offset;
51790 	dist_sce = 0; DUK_UNREF(dist_sce);  /* initialize for debug prints, needed if sce==NULL */
51791 
51792 	p_start = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
51793 	p_end = (const duk_uint8_t *) (p_start + DUK_HSTRING_GET_BYTELEN(h));
51794 	p_found = NULL;
51795 
51796 	if (sce) {
51797 		if (char_offset >= sce->cidx) {
51798 			dist_sce = char_offset - sce->cidx;
51799 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
51800 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51801 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51802 				                     "scan forwards from sce",
51803 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51804 				                     (sce ? (long) sce->cidx : (long) -1),
51805 				                     (sce ? (long) sce->bidx : (long) -1),
51806 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
51807 
51808 				p_found = duk__scan_forwards(p_start + sce->bidx,
51809 				                             p_end,
51810 				                             dist_sce);
51811 				goto scan_done;
51812 			}
51813 		} else {
51814 			dist_sce = sce->cidx - char_offset;
51815 			if ((dist_sce <= dist_start) && (dist_sce <= dist_end)) {
51816 				DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51817 				                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51818 				                     "scan backwards from sce",
51819 				                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51820 				                     (sce ? (long) sce->cidx : (long) -1),
51821 				                     (sce ? (long) sce->bidx : (long) -1),
51822 				                     (long) dist_start, (long) dist_end, (long) dist_sce));
51823 
51824 				p_found = duk__scan_backwards(p_start + sce->bidx,
51825 				                              p_start,
51826 				                              dist_sce);
51827 				goto scan_done;
51828 			}
51829 		}
51830 	}
51831 
51832 	/* no sce, or sce scan not best */
51833 
51834 	if (dist_start <= dist_end) {
51835 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51836 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51837 		                     "scan forwards from string start",
51838 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51839 		                     (sce ? (long) sce->cidx : (long) -1),
51840 		                     (sce ? (long) sce->bidx : (long) -1),
51841 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
51842 
51843 		p_found = duk__scan_forwards(p_start,
51844 		                             p_end,
51845 		                             dist_start);
51846 	} else {
51847 		DUK_DDD(DUK_DDDPRINT("non-ascii string, use_cache=%ld, sce=%p:%ld:%ld, "
51848 		                     "dist_start=%ld, dist_end=%ld, dist_sce=%ld => "
51849 		                     "scan backwards from string end",
51850 		                     (long) use_cache, (void *) (sce ? sce->h : NULL),
51851 		                     (sce ? (long) sce->cidx : (long) -1),
51852 		                     (sce ? (long) sce->bidx : (long) -1),
51853 		                     (long) dist_start, (long) dist_end, (long) dist_sce));
51854 
51855 		p_found = duk__scan_backwards(p_end,
51856 		                              p_start,
51857 		                              dist_end);
51858 	}
51859 
51860  scan_done:
51861 
51862 	if (DUK_UNLIKELY(p_found == NULL)) {
51863 		/* Scan error: this shouldn't normally happen; it could happen if
51864 		 * string is not valid UTF-8 data, and clen/blen are not consistent
51865 		 * with the scanning algorithm.
51866 		 */
51867 		goto scan_error;
51868 	}
51869 
51870 	DUK_ASSERT(p_found >= p_start);
51871 	DUK_ASSERT(p_found <= p_end);  /* may be equal */
51872 	byte_offset = (duk_uint32_t) (p_found - p_start);
51873 
51874 	DUK_DDD(DUK_DDDPRINT("-> string %p, cidx %ld -> bidx %ld",
51875 	                     (void *) h, (long) char_offset, (long) byte_offset));
51876 
51877 	/*
51878 	 *  Update cache entry (allocating if necessary), and move the
51879 	 *  cache entry to the first place (in an "LRU" policy).
51880 	 */
51881 
51882 	if (use_cache) {
51883 		/* update entry, allocating if necessary */
51884 		if (!sce) {
51885 			sce = heap->strcache + DUK_HEAP_STRCACHE_SIZE - 1;  /* take last entry */
51886 			sce->h = h;
51887 		}
51888 		DUK_ASSERT(sce != NULL);
51889 		sce->bidx = (duk_uint32_t) (p_found - p_start);
51890 		sce->cidx = (duk_uint32_t) char_offset;
51891 
51892 		/* LRU: move our entry to first */
51893 		if (sce > &heap->strcache[0]) {
51894 			/*
51895 			 *   A                  C
51896 			 *   B                  A
51897 			 *   C <- sce    ==>    B
51898 			 *   D                  D
51899 			 */
51900 			duk_strcache_entry tmp;
51901 
51902 			tmp = *sce;
51903 			duk_memmove((void *) (&heap->strcache[1]),
51904 			            (const void *) (&heap->strcache[0]),
51905 			            (size_t) (((char *) sce) - ((char *) &heap->strcache[0])));
51906 			heap->strcache[0] = tmp;
51907 
51908 			/* 'sce' points to the wrong entry here, but is no longer used */
51909 		}
51910 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
51911 		DUK_DDD(DUK_DDDPRINT("stringcache after char2byte (using cache):"));
51912 		for (i = 0; i < DUK_HEAP_STRCACHE_SIZE; i++) {
51913 			duk_strcache_entry *c = heap->strcache + i;
51914 			DUK_DDD(DUK_DDDPRINT("  [%ld] -> h=%p, cidx=%ld, bidx=%ld",
51915 			                     (long) i, (void *) c->h, (long) c->cidx, (long) c->bidx));
51916 		}
51917 #endif
51918 	}
51919 
51920 	return byte_offset;
51921 
51922  scan_error:
51923 	DUK_ERROR_INTERNAL(thr);
51924 	DUK_WO_NORETURN(return 0;);
51925 }
51926 #line 1 "duk_heap_stringtable.c"
51927 /*
51928  *  Heap string table handling, string interning.
51929  */
51930 
51931 /* #include duk_internal.h -> already included */
51932 
51933 /* Resize checks not needed if minsize == maxsize, typical for low memory
51934  * targets.
51935  */
51936 #define DUK__STRTAB_RESIZE_CHECK
51937 #if (DUK_USE_STRTAB_MINSIZE == DUK_USE_STRTAB_MAXSIZE)
51938 #undef DUK__STRTAB_RESIZE_CHECK
51939 #endif
51940 
51941 #if defined(DUK_USE_STRTAB_PTRCOMP)
51942 #define DUK__HEAPPTR_ENC16(heap,ptr)    DUK_USE_HEAPPTR_ENC16((heap)->heap_udata, (ptr))
51943 #define DUK__HEAPPTR_DEC16(heap,val)    DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (val))
51944 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable16)
51945 #else
51946 #define DUK__HEAPPTR_ENC16(heap,ptr)    (ptr)
51947 #define DUK__HEAPPTR_DEC16(heap,val)    (val)
51948 #define DUK__GET_STRTABLE(heap)         ((heap)->strtable)
51949 #endif
51950 
51951 #define DUK__STRTAB_U32_MAX_STRLEN      10               /* 4'294'967'295 */
51952 
51953 /*
51954  *  Debug dump stringtable.
51955  */
51956 
51957 #if defined(DUK_USE_DEBUG)
51958 DUK_INTERNAL void duk_heap_strtable_dump(duk_heap *heap) {
51959 #if defined(DUK_USE_STRTAB_PTRCOMP)
51960 	duk_uint16_t *strtable;
51961 #else
51962 	duk_hstring **strtable;
51963 #endif
51964 	duk_uint32_t i;
51965 	duk_hstring *h;
51966 	duk_size_t count_total = 0;
51967 	duk_size_t count_chain;
51968 	duk_size_t count_chain_min = DUK_SIZE_MAX;
51969 	duk_size_t count_chain_max = 0;
51970 	duk_size_t count_len[8];  /* chain lengths from 0 to 7 */
51971 
51972 	if (heap == NULL) {
51973 		DUK_D(DUK_DPRINT("string table, heap=NULL"));
51974 		return;
51975 	}
51976 
51977 	strtable = DUK__GET_STRTABLE(heap);
51978 	if (strtable == NULL) {
51979 		DUK_D(DUK_DPRINT("string table, strtab=NULL"));
51980 		return;
51981 	}
51982 
51983 	duk_memzero((void *) count_len, sizeof(count_len));
51984 	for (i = 0; i < heap->st_size; i++) {
51985 		h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
51986 		count_chain = 0;
51987 		while (h != NULL) {
51988 			count_chain++;
51989 			h = h->hdr.h_next;
51990 		}
51991 		if (count_chain < sizeof(count_len) / sizeof(duk_size_t)) {
51992 			count_len[count_chain]++;
51993 		}
51994 		count_chain_max = (count_chain > count_chain_max ? count_chain : count_chain_max);
51995 		count_chain_min = (count_chain < count_chain_min ? count_chain : count_chain_min);
51996 		count_total += count_chain;
51997 	}
51998 
51999 	DUK_D(DUK_DPRINT("string table, strtab=%p, count=%lu, chain min=%lu max=%lu avg=%lf: "
52000 	                 "counts: %lu %lu %lu %lu %lu %lu %lu %lu ...",
52001 	                 (void *) heap->strtable, (unsigned long) count_total,
52002 	                 (unsigned long) count_chain_min, (unsigned long) count_chain_max,
52003 	                 (double) count_total / (double) heap->st_size,
52004 	                 (unsigned long) count_len[0], (unsigned long) count_len[1],
52005 	                 (unsigned long) count_len[2], (unsigned long) count_len[3],
52006 	                 (unsigned long) count_len[4], (unsigned long) count_len[5],
52007 	                 (unsigned long) count_len[6], (unsigned long) count_len[7]));
52008 }
52009 #endif  /* DUK_USE_DEBUG */
52010 
52011 /*
52012  *  Assertion helper to ensure strtable is populated correctly.
52013  */
52014 
52015 #if defined(DUK_USE_ASSERTIONS)
52016 DUK_LOCAL void duk__strtable_assert_checks(duk_heap *heap) {
52017 #if defined(DUK_USE_STRTAB_PTRCOMP)
52018 	duk_uint16_t *strtable;
52019 #else
52020 	duk_hstring **strtable;
52021 #endif
52022 	duk_uint32_t i;
52023 	duk_hstring *h;
52024 	duk_size_t count = 0;
52025 
52026 	DUK_ASSERT(heap != NULL);
52027 
52028 	strtable = DUK__GET_STRTABLE(heap);
52029 	if (strtable != NULL) {
52030 		DUK_ASSERT(heap->st_size != 0);
52031 		DUK_ASSERT(heap->st_mask == heap->st_size - 1);
52032 
52033 		for (i = 0; i < heap->st_size; i++) {
52034 			h = DUK__HEAPPTR_DEC16(heap, strtable[i]);
52035 			while (h != NULL) {
52036 				DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52037 				count++;
52038 				h = h->hdr.h_next;
52039 			}
52040 		}
52041 	} else {
52042 		DUK_ASSERT(heap->st_size == 0);
52043 		DUK_ASSERT(heap->st_mask == 0);
52044 	}
52045 
52046 #if defined(DUK__STRTAB_RESIZE_CHECK)
52047 	DUK_ASSERT(count == (duk_size_t) heap->st_count);
52048 #endif
52049 }
52050 #endif  /* DUK_USE_ASSERTIONS */
52051 
52052 /*
52053  *  Allocate and initialize a duk_hstring.
52054  *
52055  *  Returns a NULL if allocation or initialization fails for some reason.
52056  *
52057  *  The string won't be inserted into the string table and isn't tracked in
52058  *  any way (link pointers will be NULL).  The caller must place the string
52059  *  into the string table without any risk of a longjmp, otherwise the string
52060  *  is leaked.
52061  */
52062 
52063 DUK_LOCAL duk_hstring *duk__strtable_alloc_hstring(duk_heap *heap,
52064                                                    const duk_uint8_t *str,
52065                                                    duk_uint32_t blen,
52066                                                    duk_uint32_t strhash,
52067                                                    const duk_uint8_t *extdata) {
52068 	duk_hstring *res;
52069 	const duk_uint8_t *data;
52070 #if !defined(DUK_USE_HSTRING_ARRIDX)
52071 	duk_uarridx_t dummy;
52072 #endif
52073 
52074 	DUK_ASSERT(heap != NULL);
52075 	DUK_UNREF(extdata);
52076 
52077 #if defined(DUK_USE_STRLEN16)
52078 	/* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
52079 	if (blen > 0xffffUL) {
52080 		DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
52081 		goto alloc_error;
52082 	}
52083 #endif
52084 
52085 	/* XXX: Memzeroing the allocated structure is not really necessary
52086 	 * because we could just initialize all fields explicitly (almost
52087 	 * all fields are initialized explicitly anyway).
52088 	 */
52089 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52090 	if (extdata) {
52091 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring_external));
52092 		if (DUK_UNLIKELY(res == NULL)) {
52093 			goto alloc_error;
52094 		}
52095 		duk_memzero(res, sizeof(duk_hstring_external));
52096 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52097 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52098 #endif
52099 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
52100 
52101 		DUK_ASSERT(extdata[blen] == 0);  /* Application responsibility. */
52102 		data = extdata;
52103 		((duk_hstring_external *) res)->extdata = extdata;
52104 	} else
52105 #endif  /* DUK_USE_HSTRING_EXTDATA && DUK_USE_EXTSTR_INTERN_CHECK */
52106 	{
52107 		duk_uint8_t *data_tmp;
52108 
52109 		/* NUL terminate for convenient C access */
52110 		DUK_ASSERT(sizeof(duk_hstring) + blen + 1 > blen);  /* No wrap, limits ensure. */
52111 		res = (duk_hstring *) DUK_ALLOC(heap, sizeof(duk_hstring) + blen + 1);
52112 		if (DUK_UNLIKELY(res == NULL)) {
52113 			goto alloc_error;
52114 		}
52115 		duk_memzero(res, sizeof(duk_hstring));
52116 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
52117 		DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
52118 #endif
52119 		DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
52120 
52121 		data_tmp = (duk_uint8_t *) (res + 1);
52122 		duk_memcpy(data_tmp, str, blen);
52123 		data_tmp[blen] = (duk_uint8_t) 0;
52124 		data = (const duk_uint8_t *) data_tmp;
52125 	}
52126 
52127 	DUK_HSTRING_SET_BYTELEN(res, blen);
52128 	DUK_HSTRING_SET_HASH(res, strhash);
52129 
52130 	DUK_ASSERT(!DUK_HSTRING_HAS_ARRIDX(res));
52131 #if defined(DUK_USE_HSTRING_ARRIDX)
52132 	res->arridx = duk_js_to_arrayindex_string(data, blen);
52133 	if (res->arridx != DUK_HSTRING_NO_ARRAY_INDEX) {
52134 #else
52135 	dummy = duk_js_to_arrayindex_string(data, blen);
52136 	if (dummy != DUK_HSTRING_NO_ARRAY_INDEX) {
52137 #endif
52138 		/* Array index strings cannot be symbol strings,
52139 		 * and they're always pure ASCII so blen == clen.
52140 		 */
52141 		DUK_HSTRING_SET_ARRIDX(res);
52142 		DUK_HSTRING_SET_ASCII(res);
52143 		DUK_ASSERT(duk_unicode_unvalidated_utf8_length(data, (duk_size_t) blen) == blen);
52144 	} else {
52145 		/* Because 'data' is NUL-terminated, we don't need a
52146 		 * blen > 0 check here.  For NUL (0x00) the symbol
52147 		 * checks will be false.
52148 		 */
52149 		if (DUK_UNLIKELY(data[0] >= 0x80U)) {
52150 			if (data[0] <= 0x81) {
52151 				DUK_HSTRING_SET_SYMBOL(res);
52152 			} else if (data[0] == 0x82U || data[0] == 0xffU) {
52153 				DUK_HSTRING_SET_HIDDEN(res);
52154 				DUK_HSTRING_SET_SYMBOL(res);
52155 			}
52156 		}
52157 
52158 		/* Using an explicit 'ASCII' flag has larger footprint (one call site
52159 		 * only) but is quite useful for the case when there's no explicit
52160 		 * 'clen' in duk_hstring.
52161 		 *
52162 		 * The flag is set lazily for RAM strings.
52163 		 */
52164 		DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(res));
52165 
52166 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
52167 		/* Charlen initialized to 0, updated on-the-fly. */
52168 #else
52169 		duk_hstring_init_charlen(res);  /* Also sets ASCII flag. */
52170 #endif
52171 	}
52172 
52173 	DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, has_arridx=%ld, has_extdata=%ld",
52174 	                     (unsigned long) DUK_HSTRING_GET_HASH(res),
52175 	                     (long) DUK_HSTRING_GET_BYTELEN(res),
52176 	                     (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
52177 	                     (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
52178 
52179 	DUK_ASSERT(res != NULL);
52180 	return res;
52181 
52182  alloc_error:
52183 	return NULL;
52184 }
52185 
52186 /*
52187  *  Grow strtable allocation in-place.
52188  */
52189 
52190 #if defined(DUK__STRTAB_RESIZE_CHECK)
52191 DUK_LOCAL void duk__strtable_grow_inplace(duk_heap *heap) {
52192 	duk_uint32_t new_st_size;
52193 	duk_uint32_t old_st_size;
52194 	duk_uint32_t i;
52195 	duk_hstring *h;
52196 	duk_hstring *next;
52197 	duk_hstring *prev;
52198 #if defined(DUK_USE_STRTAB_PTRCOMP)
52199 	duk_uint16_t *new_ptr;
52200 	duk_uint16_t *new_ptr_high;
52201 #else
52202 	duk_hstring **new_ptr;
52203 	duk_hstring **new_ptr_high;
52204 #endif
52205 
52206 	DUK_DD(DUK_DDPRINT("grow in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52207 
52208 	DUK_ASSERT(heap != NULL);
52209 	DUK_ASSERT(heap->st_resizing == 1);
52210 	DUK_ASSERT(heap->st_size >= 2);
52211 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52212 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52213 
52214 	DUK_STATS_INC(heap, stats_strtab_resize_grow);
52215 
52216 	new_st_size = heap->st_size << 1U;
52217 	DUK_ASSERT(new_st_size > heap->st_size);  /* No overflow. */
52218 
52219 	/* Reallocate the strtable first and then work in-place to rehash
52220 	 * strings.  We don't need an indirect allocation here: even if GC
52221 	 * is triggered to satisfy the allocation, recursive strtable resize
52222 	 * is prevented by flags.  This is also why we don't need to use
52223 	 * DUK_REALLOC_INDIRECT().
52224 	 */
52225 
52226 #if defined(DUK_USE_STRTAB_PTRCOMP)
52227 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52228 #else
52229 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52230 #endif
52231 	if (DUK_UNLIKELY(new_ptr == NULL)) {
52232 		/* If realloc fails we can continue normally: the string table
52233 		 * won't "fill up" although chains will gradually get longer.
52234 		 * When string insertions continue, we'll quite soon try again
52235 		 * with no special handling.
52236 		 */
52237 		DUK_D(DUK_DPRINT("string table grow failed, ignoring"));
52238 		return;
52239 	}
52240 #if defined(DUK_USE_STRTAB_PTRCOMP)
52241 	heap->strtable16 = new_ptr;
52242 #else
52243 	heap->strtable = new_ptr;
52244 #endif
52245 
52246 	/* Rehash a single bucket into two separate ones.  When we grow
52247 	 * by x2 the highest 'new' bit determines whether a string remains
52248 	 * in its old position (bit is 0) or goes to a new one (bit is 1).
52249 	 */
52250 
52251 	old_st_size = heap->st_size;
52252 	new_ptr_high = new_ptr + old_st_size;
52253 	for (i = 0; i < old_st_size; i++) {
52254 		duk_hstring *new_root;
52255 		duk_hstring *new_root_high;
52256 
52257 		h = DUK__HEAPPTR_DEC16(heap, new_ptr[i]);
52258 		new_root = h;
52259 		new_root_high = NULL;
52260 
52261 		prev = NULL;
52262 		while (h != NULL) {
52263 			duk_uint32_t mask;
52264 
52265 			DUK_ASSERT((DUK_HSTRING_GET_HASH(h) & heap->st_mask) == i);
52266 			next = h->hdr.h_next;
52267 
52268 			/* Example: if previous size was 256, previous mask is 0xFF
52269 			 * and size is 0x100 which corresponds to the new bit that
52270 			 * comes into play.
52271 			 */
52272 			DUK_ASSERT(heap->st_mask == old_st_size - 1);
52273 			mask = old_st_size;
52274 			if (DUK_HSTRING_GET_HASH(h) & mask) {
52275 				if (prev != NULL) {
52276 					prev->hdr.h_next = h->hdr.h_next;
52277 				} else {
52278 					DUK_ASSERT(h == new_root);
52279 					new_root = h->hdr.h_next;
52280 				}
52281 
52282 				h->hdr.h_next = new_root_high;
52283 				new_root_high = h;
52284 			} else {
52285 				prev = h;
52286 			}
52287 			h = next;
52288 		}
52289 
52290 		new_ptr[i] = DUK__HEAPPTR_ENC16(heap, new_root);
52291 		new_ptr_high[i] = DUK__HEAPPTR_ENC16(heap, new_root_high);
52292 	}
52293 
52294 	heap->st_size = new_st_size;
52295 	heap->st_mask = new_st_size - 1;
52296 
52297 #if defined(DUK_USE_ASSERTIONS)
52298 	duk__strtable_assert_checks(heap);
52299 #endif
52300 }
52301 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52302 
52303 /*
52304  *  Shrink strtable allocation in-place.
52305  */
52306 
52307 #if defined(DUK__STRTAB_RESIZE_CHECK)
52308 DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
52309 	duk_uint32_t new_st_size;
52310 	duk_uint32_t i;
52311 	duk_hstring *h;
52312 	duk_hstring *other;
52313 	duk_hstring *root;
52314 #if defined(DUK_USE_STRTAB_PTRCOMP)
52315 	duk_uint16_t *old_ptr;
52316 	duk_uint16_t *old_ptr_high;
52317 	duk_uint16_t *new_ptr;
52318 #else
52319 	duk_hstring **old_ptr;
52320 	duk_hstring **old_ptr_high;
52321 	duk_hstring **new_ptr;
52322 #endif
52323 
52324 	DUK_DD(DUK_DDPRINT("shrink in-place: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52325 
52326 	DUK_ASSERT(heap != NULL);
52327 	DUK_ASSERT(heap->st_resizing == 1);
52328 	DUK_ASSERT(heap->st_size >= 2);
52329 	DUK_ASSERT((heap->st_size & (heap->st_size - 1)) == 0);  /* 2^N */
52330 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52331 
52332 	DUK_STATS_INC(heap, stats_strtab_resize_shrink);
52333 
52334 	new_st_size = heap->st_size >> 1U;
52335 
52336 	/* Combine two buckets into a single one.  When we shrink, one hash
52337 	 * bit (highest) disappears.
52338 	 */
52339 	old_ptr = DUK__GET_STRTABLE(heap);
52340 	old_ptr_high = old_ptr + new_st_size;
52341 	for (i = 0; i < new_st_size; i++) {
52342 		h = DUK__HEAPPTR_DEC16(heap, old_ptr[i]);
52343 		other = DUK__HEAPPTR_DEC16(heap, old_ptr_high[i]);
52344 
52345 		if (h == NULL) {
52346 			/* First chain is empty, so use second one as is. */
52347 			root = other;
52348 		} else {
52349 			/* Find end of first chain, and link in the second. */
52350 			root = h;
52351 			while (h->hdr.h_next != NULL) {
52352 				h = h->hdr.h_next;
52353 			}
52354 			h->hdr.h_next = other;
52355 		}
52356 
52357 		old_ptr[i] = DUK__HEAPPTR_ENC16(heap, root);
52358 	}
52359 
52360 	heap->st_size = new_st_size;
52361 	heap->st_mask = new_st_size - 1;
52362 
52363 	/* The strtable is now consistent and we can realloc safely.  Even
52364 	 * if side effects cause string interning or removal the strtable
52365 	 * updates are safe.  Recursive resize has been prevented by caller.
52366 	 * This is also why we don't need to use DUK_REALLOC_INDIRECT().
52367 	 *
52368 	 * We assume a realloc() to a smaller size is guaranteed to succeed.
52369 	 * It would be relatively straightforward to handle the error by
52370 	 * essentially performing a "grow" step to recover.
52371 	 */
52372 
52373 #if defined(DUK_USE_STRTAB_PTRCOMP)
52374 	new_ptr = (duk_uint16_t *) DUK_REALLOC(heap, heap->strtable16, sizeof(duk_uint16_t) * new_st_size);
52375 	DUK_ASSERT(new_ptr != NULL);
52376 	heap->strtable16 = new_ptr;
52377 #else
52378 	new_ptr = (duk_hstring **) DUK_REALLOC(heap, heap->strtable, sizeof(duk_hstring *) * new_st_size);
52379 	DUK_ASSERT(new_ptr != NULL);
52380 	heap->strtable = new_ptr;
52381 #endif
52382 
52383 #if defined(DUK_USE_ASSERTIONS)
52384 	duk__strtable_assert_checks(heap);
52385 #endif
52386 }
52387 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52388 
52389 /*
52390  *  Grow/shrink check.
52391  */
52392 
52393 #if defined(DUK__STRTAB_RESIZE_CHECK)
52394 DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
52395 	duk_uint32_t load_factor;  /* fixed point */
52396 
52397 	DUK_ASSERT(heap != NULL);
52398 #if defined(DUK_USE_STRTAB_PTRCOMP)
52399 	DUK_ASSERT(heap->strtable16 != NULL);
52400 #else
52401 	DUK_ASSERT(heap->strtable != NULL);
52402 #endif
52403 
52404 	DUK_STATS_INC(heap, stats_strtab_resize_check);
52405 
52406 	/* Prevent recursive resizing. */
52407 	if (DUK_UNLIKELY(heap->st_resizing != 0U)) {
52408 		DUK_D(DUK_DPRINT("prevent recursive strtable resize"));
52409 		return;
52410 	}
52411 
52412 	heap->st_resizing = 1;
52413 
52414 	DUK_ASSERT(heap->st_size >= 16U);
52415 	DUK_ASSERT((heap->st_size >> 4U) >= 1);
52416 	load_factor = heap->st_count / (heap->st_size >> 4U);
52417 
52418 	DUK_DD(DUK_DDPRINT("resize check string table: size=%lu, count=%lu, load_factor=%lu (fixed point .4; float %lf)",
52419 	                   (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52420 	                   (unsigned long) load_factor,
52421 	                   (double) heap->st_count / (double) heap->st_size));
52422 
52423 	if (load_factor >= DUK_USE_STRTAB_GROW_LIMIT) {
52424 		if (heap->st_size >= DUK_USE_STRTAB_MAXSIZE) {
52425 			DUK_DD(DUK_DDPRINT("want to grow strtable (based on load factor) but already maximum size"));
52426 		} else {
52427 			DUK_D(DUK_DPRINT("grow string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size * 2));
52428 #if defined(DUK_USE_DEBUG)
52429 			duk_heap_strtable_dump(heap);
52430 #endif
52431 			duk__strtable_grow_inplace(heap);
52432 		}
52433 	} else if (load_factor <= DUK_USE_STRTAB_SHRINK_LIMIT) {
52434 		if (heap->st_size <= DUK_USE_STRTAB_MINSIZE) {
52435 			DUK_DD(DUK_DDPRINT("want to shrink strtable (based on load factor) but already minimum size"));
52436 		} else {
52437 			DUK_D(DUK_DPRINT("shrink string table: %lu -> %lu", (unsigned long) heap->st_size, (unsigned long) heap->st_size / 2));
52438 #if defined(DUK_USE_DEBUG)
52439 			duk_heap_strtable_dump(heap);
52440 #endif
52441 			duk__strtable_shrink_inplace(heap);
52442 		}
52443 	} else {
52444 		DUK_DD(DUK_DDPRINT("no need for strtable resize"));
52445 	}
52446 
52447 	heap->st_resizing = 0;
52448 }
52449 #endif  /* DUK__STRTAB_RESIZE_CHECK */
52450 
52451 /*
52452  *  Torture grow/shrink: unconditionally grow and shrink back.
52453  */
52454 
52455 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52456 DUK_LOCAL void duk__strtable_resize_torture(duk_heap *heap) {
52457 	duk_uint32_t old_st_size;
52458 
52459 	DUK_ASSERT(heap != NULL);
52460 
52461 	old_st_size = heap->st_size;
52462 	if (old_st_size >= DUK_USE_STRTAB_MAXSIZE) {
52463 		return;
52464 	}
52465 
52466 	heap->st_resizing = 1;
52467 	duk__strtable_grow_inplace(heap);
52468 	if (heap->st_size > old_st_size) {
52469 		duk__strtable_shrink_inplace(heap);
52470 	}
52471 	heap->st_resizing = 0;
52472 }
52473 #endif  /* DUK_USE_STRTAB_TORTURE && DUK__STRTAB_RESIZE_CHECK */
52474 
52475 /*
52476  *  Raw intern; string already checked not to be present.
52477  */
52478 
52479 DUK_LOCAL duk_hstring *duk__strtable_do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
52480 	duk_hstring *res;
52481 	const duk_uint8_t *extdata;
52482 #if defined(DUK_USE_STRTAB_PTRCOMP)
52483 	duk_uint16_t *slot;
52484 #else
52485 	duk_hstring **slot;
52486 #endif
52487 
52488 	DUK_DDD(DUK_DDDPRINT("do_intern: heap=%p, str=%p, blen=%lu, strhash=%lx, st_size=%lu, st_count=%lu, load=%lf",
52489 	                     (void *) heap, (const void *) str, (unsigned long) blen, (unsigned long) strhash,
52490 	                     (unsigned long) heap->st_size, (unsigned long) heap->st_count,
52491 	                     (double) heap->st_count / (double) heap->st_size));
52492 
52493 	DUK_ASSERT(heap != NULL);
52494 
52495 	/* Prevent any side effects on the string table and the caller provided
52496 	 * str/blen arguments while interning is in progress.  For example, if
52497 	 * the caller provided str/blen from a dynamic buffer, a finalizer
52498 	 * might resize or modify that dynamic buffer, invalidating the call
52499 	 * arguments.
52500 	 *
52501 	 * While finalizers must be prevented, mark-and-sweep itself is fine.
52502 	 * Recursive string table resize is prevented explicitly here.
52503 	 */
52504 
52505 	heap->pf_prevent_count++;
52506 	DUK_ASSERT(heap->pf_prevent_count != 0);  /* Wrap. */
52507 
52508 #if defined(DUK_USE_STRTAB_TORTURE) && defined(DUK__STRTAB_RESIZE_CHECK)
52509 	duk__strtable_resize_torture(heap);
52510 #endif
52511 
52512 	/* String table grow/shrink check.  Because of chaining (and no
52513 	 * accumulation issues as with hash probe chains and DELETED
52514 	 * markers) there's never a mandatory need to resize right now.
52515 	 * Check for the resize only periodically, based on st_count
52516 	 * bit pattern.  Because string table removal doesn't do a shrink
52517 	 * check, we do that also here.
52518 	 *
52519 	 * Do the resize and possible grow/shrink before the new duk_hstring
52520 	 * has been allocated.  Otherwise we may trigger a GC when the result
52521 	 * duk_hstring is not yet strongly referenced.
52522 	 */
52523 
52524 #if defined(DUK__STRTAB_RESIZE_CHECK)
52525 	if (DUK_UNLIKELY((heap->st_count & DUK_USE_STRTAB_RESIZE_CHECK_MASK) == 0)) {
52526 		duk__strtable_resize_check(heap);
52527 	}
52528 #endif
52529 
52530 	/* External string check (low memory optimization). */
52531 
52532 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52533 	extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
52534 #else
52535 	extdata = (const duk_uint8_t *) NULL;
52536 #endif
52537 
52538 	/* Allocate and initialize string, not yet linked.  This may cause a
52539 	 * GC which may cause other strings to be interned and inserted into
52540 	 * the string table before we insert our string.  Finalizer execution
52541 	 * is disabled intentionally to avoid a finalizer from e.g. resizing
52542 	 * a buffer used as a data area for 'str'.
52543 	 */
52544 
52545 	res = duk__strtable_alloc_hstring(heap, str, blen, strhash, extdata);
52546 
52547 	/* Allow side effects again: GC must be avoided until duk_hstring
52548 	 * result (if successful) has been INCREF'd.
52549 	 */
52550 	DUK_ASSERT(heap->pf_prevent_count > 0);
52551 	heap->pf_prevent_count--;
52552 
52553 	/* Alloc error handling. */
52554 
52555 	if (DUK_UNLIKELY(res == NULL)) {
52556 #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
52557 		if (extdata != NULL) {
52558 			DUK_USE_EXTSTR_FREE(heap->heap_udata, (const void *) extdata);
52559 		}
52560 #endif
52561 		return NULL;
52562 	}
52563 
52564 	/* Insert into string table. */
52565 
52566 #if defined(DUK_USE_STRTAB_PTRCOMP)
52567 	slot = heap->strtable16 + (strhash & heap->st_mask);
52568 #else
52569 	slot = heap->strtable + (strhash & heap->st_mask);
52570 #endif
52571 	DUK_ASSERT(res->hdr.h_next == NULL);  /* This is the case now, but unnecessary zeroing/NULLing. */
52572 	res->hdr.h_next = DUK__HEAPPTR_DEC16(heap, *slot);
52573 	*slot = DUK__HEAPPTR_ENC16(heap, res);
52574 
52575 	/* Update string count only for successful inserts. */
52576 
52577 #if defined(DUK__STRTAB_RESIZE_CHECK)
52578 	heap->st_count++;
52579 #endif
52580 
52581 	/* The duk_hstring is in the string table but is not yet strongly
52582 	 * reachable.  Calling code MUST NOT make any allocations or other
52583 	 * side effects before the duk_hstring has been INCREF'd and made
52584 	 * reachable.
52585 	 */
52586 
52587 	return res;
52588 }
52589 
52590 /*
52591  *  Intern a string from str/blen, returning either an existing duk_hstring
52592  *  or adding a new one into the string table.  The input string does -not-
52593  *  need to be NUL terminated.
52594  *
52595  *  The input 'str' argument may point to a Duktape managed data area such as
52596  *  the data area of a dynamic buffer.  It's crucial to avoid any side effects
52597  *  that might affect the data area (e.g. resize the dynamic buffer, or write
52598  *  to the buffer) before the string is fully interned.
52599  */
52600 
52601 #if defined(DUK_USE_ROM_STRINGS)
52602 DUK_LOCAL duk_hstring *duk__strtab_romstring_lookup(duk_heap *heap, const duk_uint8_t *str, duk_size_t blen, duk_uint32_t strhash) {
52603 	duk_size_t lookup_hash;
52604 	duk_hstring *curr;
52605 
52606 	DUK_ASSERT(heap != NULL);
52607 	DUK_UNREF(heap);
52608 
52609 	lookup_hash = (blen << 4);
52610 	if (blen > 0) {
52611 		lookup_hash += str[0];
52612 	}
52613 	lookup_hash &= 0xff;
52614 
52615 	curr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_lookup[lookup_hash]);
52616 	while (curr != NULL) {
52617 		/* Unsafe memcmp() because for zero blen, str may be NULL. */
52618 		if (strhash == DUK_HSTRING_GET_HASH(curr) &&
52619 		    blen == DUK_HSTRING_GET_BYTELEN(curr) &&
52620 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(curr), blen) == 0) {
52621 			DUK_DDD(DUK_DDDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
52622 			                     curr, (unsigned long) strhash, (unsigned long) DUK_HSTRING_GET_HASH(curr)));
52623 			return curr;
52624 		}
52625 		curr = curr->hdr.h_next;
52626 	}
52627 
52628 	return NULL;
52629 }
52630 #endif  /* DUK_USE_ROM_STRINGS */
52631 
52632 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen) {
52633 	duk_uint32_t strhash;
52634 	duk_hstring *h;
52635 
52636 	DUK_DDD(DUK_DDDPRINT("intern check: heap=%p, str=%p, blen=%lu", (void *) heap, (const void *) str, (unsigned long) blen));
52637 
52638 	/* Preliminaries. */
52639 
52640 	/* XXX: maybe just require 'str != NULL' even for zero size? */
52641 	DUK_ASSERT(heap != NULL);
52642 	DUK_ASSERT(blen == 0 || str != NULL);
52643 	DUK_ASSERT(blen <= DUK_HSTRING_MAX_BYTELEN);  /* Caller is responsible for ensuring this. */
52644 	strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
52645 
52646 	/* String table lookup. */
52647 
52648 	DUK_ASSERT(DUK__GET_STRTABLE(heap) != NULL);
52649 	DUK_ASSERT(heap->st_size > 0);
52650 	DUK_ASSERT(heap->st_size == heap->st_mask + 1);
52651 #if defined(DUK_USE_STRTAB_PTRCOMP)
52652 	h = DUK__HEAPPTR_DEC16(heap, heap->strtable16[strhash & heap->st_mask]);
52653 #else
52654 	h = heap->strtable[strhash & heap->st_mask];
52655 #endif
52656 	while (h != NULL) {
52657 		if (DUK_HSTRING_GET_HASH(h) == strhash &&
52658 		    DUK_HSTRING_GET_BYTELEN(h) == blen &&
52659 		    duk_memcmp_unsafe((const void *) str, (const void *) DUK_HSTRING_GET_DATA(h), (size_t) blen) == 0) {
52660 			/* Found existing entry. */
52661 			DUK_STATS_INC(heap, stats_strtab_intern_hit);
52662 			return h;
52663 		}
52664 		h = h->hdr.h_next;
52665 	}
52666 
52667 	/* ROM table lookup.  Because this lookup is slower, do it only after
52668 	 * RAM lookup.  This works because no ROM string is ever interned into
52669 	 * the RAM string table.
52670 	 */
52671 
52672 #if defined(DUK_USE_ROM_STRINGS)
52673 	h = duk__strtab_romstring_lookup(heap, str, blen, strhash);
52674 	if (h != NULL) {
52675 		DUK_STATS_INC(heap, stats_strtab_intern_hit);
52676 		return h;
52677 	}
52678 #endif
52679 
52680 	/* Not found in string table; insert. */
52681 
52682 	DUK_STATS_INC(heap, stats_strtab_intern_miss);
52683 	h = duk__strtable_do_intern(heap, str, blen, strhash);
52684 	return h;  /* may be NULL */
52685 }
52686 
52687 /*
52688  *  Intern a string from u32.
52689  */
52690 
52691 /* XXX: Could arrange some special handling because we know that the result
52692  * will have an arridx flag and an ASCII flag, won't need a clen check, etc.
52693  */
52694 
52695 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32(duk_heap *heap, duk_uint32_t val) {
52696 	duk_uint8_t buf[DUK__STRTAB_U32_MAX_STRLEN];
52697 	duk_uint8_t *p;
52698 
52699 	DUK_ASSERT(heap != NULL);
52700 
52701 	/* This is smaller and faster than a %lu sprintf. */
52702 	p = buf + sizeof(buf);
52703 	do {
52704 		p--;
52705 		*p = duk_lc_digits[val % 10];
52706 		val = val / 10;
52707 	} while (val != 0);  /* For val == 0, emit exactly one '0'. */
52708 	DUK_ASSERT(p >= buf);
52709 
52710 	return duk_heap_strtable_intern(heap, (const duk_uint8_t *) p, (duk_uint32_t) ((buf + sizeof(buf)) - p));
52711 }
52712 
52713 /*
52714  *  Checked convenience variants.
52715  *
52716  *  XXX: Because the main use case is for the checked variants, make them the
52717  *  main functionality and provide a safe variant separately (it is only needed
52718  *  during heap init).  The problem with that is that longjmp state and error
52719  *  creation must already be possible to throw.
52720  */
52721 
52722 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
52723 	duk_hstring *res;
52724 
52725 	DUK_ASSERT(thr != NULL);
52726 	DUK_ASSERT(thr->heap != NULL);
52727 	DUK_ASSERT(blen == 0 || str != NULL);
52728 
52729 	res = duk_heap_strtable_intern(thr->heap, str, blen);
52730 	if (DUK_UNLIKELY(res == NULL)) {
52731 		DUK_ERROR_ALLOC_FAILED(thr);
52732 		DUK_WO_NORETURN(return NULL;);
52733 	}
52734 	return res;
52735 }
52736 
52737 #if defined(DUK_USE_LITCACHE_SIZE)
52738 DUK_LOCAL duk_uint_t duk__strtable_litcache_key(const duk_uint8_t *str, duk_uint32_t blen) {
52739 	duk_uintptr_t key;
52740 
52741 	DUK_ASSERT(DUK_USE_LITCACHE_SIZE > 0);
52742 	DUK_ASSERT(DUK_IS_POWER_OF_TWO((duk_uint_t) DUK_USE_LITCACHE_SIZE));
52743 
52744 	key = (duk_uintptr_t) blen ^ (duk_uintptr_t) str;
52745 	key &= (duk_uintptr_t) (DUK_USE_LITCACHE_SIZE - 1);  /* Assumes size is power of 2. */
52746 	/* Due to masking, cast is in 32-bit range. */
52747 	DUK_ASSERT(key <= DUK_UINT_MAX);
52748 	return (duk_uint_t) key;
52749 }
52750 
52751 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_literal_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen) {
52752 	duk_uint_t key;
52753 	duk_litcache_entry *ent;
52754 	duk_hstring *h;
52755 
52756 	/* Fast path check: literal exists in literal cache. */
52757 	key = duk__strtable_litcache_key(str, blen);
52758 	ent = thr->heap->litcache + key;
52759 	if (ent->addr == str) {
52760 		DUK_DD(DUK_DDPRINT("intern check for cached, pinned literal: str=%p, blen=%ld -> duk_hstring %!O",
52761 		                   (const void *) str, (long) blen, (duk_heaphdr *) ent->h));
52762 		DUK_ASSERT(ent->h != NULL);
52763 		DUK_ASSERT(DUK_HSTRING_HAS_PINNED_LITERAL(ent->h));
52764 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_hit);
52765 		return ent->h;
52766 	}
52767 
52768 	/* Intern and update (overwrite) cache entry. */
52769 	h = duk_heap_strtable_intern_checked(thr, str, blen);
52770 	ent->addr = str;
52771 	ent->h = h;
52772 	DUK_STATS_INC(thr->heap, stats_strtab_litcache_miss);
52773 
52774 	/* Pin the duk_hstring until the next mark-and-sweep.  This means
52775 	 * litcache entries don't need to be invalidated until the next
52776 	 * mark-and-sweep as their target duk_hstring is not freed before
52777 	 * the mark-and-sweep happens.  The pin remains even if the literal
52778 	 * cache entry is overwritten, and is still useful to avoid string
52779 	 * table traffic.
52780 	 */
52781 	if (!DUK_HSTRING_HAS_PINNED_LITERAL(h)) {
52782 		DUK_DD(DUK_DDPRINT("pin duk_hstring because it is a literal: %!O", (duk_heaphdr *) h));
52783 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
52784 		DUK_HSTRING_INCREF(thr, h);
52785 		DUK_HSTRING_SET_PINNED_LITERAL(h);
52786 		DUK_STATS_INC(thr->heap, stats_strtab_litcache_pin);
52787 	}
52788 
52789 	return h;
52790 }
52791 #endif  /* DUK_USE_LITCACHE_SIZE */
52792 
52793 DUK_INTERNAL duk_hstring *duk_heap_strtable_intern_u32_checked(duk_hthread *thr, duk_uint32_t val) {
52794 	duk_hstring *res;
52795 
52796 	DUK_ASSERT(thr != NULL);
52797 	DUK_ASSERT(thr->heap != NULL);
52798 
52799 	res = duk_heap_strtable_intern_u32(thr->heap, val);
52800 	if (DUK_UNLIKELY(res == NULL)) {
52801 		DUK_ERROR_ALLOC_FAILED(thr);
52802 		DUK_WO_NORETURN(return NULL;);
52803 	}
52804 	return res;
52805 }
52806 
52807 /*
52808  *  Remove (unlink) a string from the string table.
52809  *
52810  *  Just unlinks the duk_hstring, leaving link pointers as garbage.
52811  *  Caller must free the string itself.
52812  */
52813 
52814 #if defined(DUK_USE_REFERENCE_COUNTING)
52815 /* Unlink without a 'prev' pointer. */
52816 DUK_INTERNAL void duk_heap_strtable_unlink(duk_heap *heap, duk_hstring *h) {
52817 #if defined(DUK_USE_STRTAB_PTRCOMP)
52818 	duk_uint16_t *slot;
52819 #else
52820 	duk_hstring **slot;
52821 #endif
52822 	duk_hstring *other;
52823 	duk_hstring *prev;
52824 
52825 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, h=%p, blen=%lu, strhash=%lx",
52826 	                     (void *) heap, (void *) h,
52827 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
52828 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
52829 
52830 	DUK_ASSERT(heap != NULL);
52831 	DUK_ASSERT(h != NULL);
52832 
52833 #if defined(DUK__STRTAB_RESIZE_CHECK)
52834 	DUK_ASSERT(heap->st_count > 0);
52835 	heap->st_count--;
52836 #endif
52837 
52838 #if defined(DUK_USE_STRTAB_PTRCOMP)
52839 	slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52840 #else
52841 	slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52842 #endif
52843 	other = DUK__HEAPPTR_DEC16(heap, *slot);
52844 	DUK_ASSERT(other != NULL);  /* At least argument string is in the chain. */
52845 
52846 	prev = NULL;
52847 	while (other != h) {
52848 		prev = other;
52849 		other = other->hdr.h_next;
52850 		DUK_ASSERT(other != NULL);  /* We'll eventually find 'h'. */
52851 	}
52852 	if (prev != NULL) {
52853 		/* Middle of list. */
52854 		prev->hdr.h_next = h->hdr.h_next;
52855 	} else {
52856 		/* Head of list. */
52857 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
52858 	}
52859 
52860 	/* There's no resize check on a string free.  The next string
52861 	 * intern will do one.
52862 	 */
52863 }
52864 #endif  /* DUK_USE_REFERENCE_COUNTING */
52865 
52866 /* Unlink with a 'prev' pointer. */
52867 DUK_INTERNAL void duk_heap_strtable_unlink_prev(duk_heap *heap, duk_hstring *h, duk_hstring *prev) {
52868 #if defined(DUK_USE_STRTAB_PTRCOMP)
52869 	duk_uint16_t *slot;
52870 #else
52871 	duk_hstring **slot;
52872 #endif
52873 
52874 	DUK_DDD(DUK_DDDPRINT("remove: heap=%p, prev=%p, h=%p, blen=%lu, strhash=%lx",
52875 	                     (void *) heap, (void *) prev, (void *) h,
52876 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_BYTELEN(h) : 0),
52877 	                     (unsigned long) (h != NULL ? DUK_HSTRING_GET_HASH(h) : 0)));
52878 
52879 	DUK_ASSERT(heap != NULL);
52880 	DUK_ASSERT(h != NULL);
52881 	DUK_ASSERT(prev == NULL || prev->hdr.h_next == h);
52882 
52883 #if defined(DUK__STRTAB_RESIZE_CHECK)
52884 	DUK_ASSERT(heap->st_count > 0);
52885 	heap->st_count--;
52886 #endif
52887 
52888 	if (prev != NULL) {
52889 		/* Middle of list. */
52890 		prev->hdr.h_next = h->hdr.h_next;
52891 	} else {
52892 		/* Head of list. */
52893 #if defined(DUK_USE_STRTAB_PTRCOMP)
52894 		slot = heap->strtable16 + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52895 #else
52896 		slot = heap->strtable + (DUK_HSTRING_GET_HASH(h) & heap->st_mask);
52897 #endif
52898 		DUK_ASSERT(DUK__HEAPPTR_DEC16(heap, *slot) == h);
52899 		*slot = DUK__HEAPPTR_ENC16(heap, h->hdr.h_next);
52900 	}
52901 }
52902 
52903 /*
52904  *  Force string table resize check in mark-and-sweep.
52905  */
52906 
52907 DUK_INTERNAL void duk_heap_strtable_force_resize(duk_heap *heap) {
52908 	/* Does only one grow/shrink step if needed.  The heap->st_resizing
52909 	 * flag protects against recursive resizing.
52910 	 */
52911 
52912 	DUK_ASSERT(heap != NULL);
52913 	DUK_UNREF(heap);
52914 
52915 #if defined(DUK__STRTAB_RESIZE_CHECK)
52916 #if defined(DUK_USE_STRTAB_PTRCOMP)
52917 	if (heap->strtable16 != NULL) {
52918 #else
52919 	if (heap->strtable != NULL) {
52920 #endif
52921 		duk__strtable_resize_check(heap);
52922 	}
52923 #endif
52924 }
52925 
52926 /*
52927  *  Free strings in the string table and the string table itself.
52928  */
52929 
52930 DUK_INTERNAL void duk_heap_strtable_free(duk_heap *heap) {
52931 #if defined(DUK_USE_STRTAB_PTRCOMP)
52932 	duk_uint16_t *strtable;
52933 	duk_uint16_t *st;
52934 #else
52935 	duk_hstring **strtable;
52936 	duk_hstring **st;
52937 #endif
52938 	duk_hstring *h;
52939 
52940 	DUK_ASSERT(heap != NULL);
52941 
52942 #if defined(DUK_USE_ASSERTIONS)
52943 	duk__strtable_assert_checks(heap);
52944 #endif
52945 
52946 	/* Strtable can be NULL if heap init fails.  However, in that case
52947 	 * heap->st_size is 0, so strtable == strtable_end and we skip the
52948 	 * loop without a special check.
52949 	 */
52950 	strtable = DUK__GET_STRTABLE(heap);
52951 	st = strtable + heap->st_size;
52952 	DUK_ASSERT(strtable != NULL || heap->st_size == 0);
52953 
52954 	while (strtable != st) {
52955 		--st;
52956 		h = DUK__HEAPPTR_DEC16(heap, *st);
52957 		while (h) {
52958 			duk_hstring *h_next;
52959 			h_next = h->hdr.h_next;
52960 
52961 			/* Strings may have inner refs (extdata) in some cases. */
52962 			duk_free_hstring(heap, h);
52963 
52964 			h = h_next;
52965 		}
52966 	}
52967 
52968 	DUK_FREE(heap, strtable);
52969 }
52970 
52971 /* automatic undefs */
52972 #undef DUK__GET_STRTABLE
52973 #undef DUK__HEAPPTR_DEC16
52974 #undef DUK__HEAPPTR_ENC16
52975 #undef DUK__STRTAB_U32_MAX_STRLEN
52976 #line 1 "duk_hobject_alloc.c"
52977 /*
52978  *  Hobject allocation.
52979  *
52980  *  Provides primitive allocation functions for all object types (plain object,
52981  *  compiled function, native function, thread).  The object return is not yet
52982  *  in "heap allocated" list and has a refcount of zero, so caller must careful.
52983  */
52984 
52985 /* XXX: In most cases there's no need for plain allocation without pushing
52986  * to the value stack.  Maybe rework contract?
52987  */
52988 
52989 /* #include duk_internal.h -> already included */
52990 
52991 /*
52992  *  Helpers.
52993  */
52994 
52995 DUK_LOCAL void duk__init_object_parts(duk_heap *heap, duk_uint_t hobject_flags, duk_hobject *obj) {
52996 	DUK_ASSERT(obj != NULL);
52997 	/* Zeroed by caller. */
52998 
52999 	obj->hdr.h_flags = hobject_flags | DUK_HTYPE_OBJECT;
53000 	DUK_ASSERT(DUK_HEAPHDR_GET_TYPE(&obj->hdr) == DUK_HTYPE_OBJECT);  /* Assume zero shift. */
53001 
53002 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53003 	DUK_HOBJECT_SET_PROTOTYPE(heap, obj, NULL);
53004 	DUK_HOBJECT_SET_PROPS(heap, obj, NULL);
53005 #endif
53006 #if defined(DUK_USE_HEAPPTR16)
53007 	/* Zero encoded pointer is required to match NULL. */
53008 	DUK_HEAPHDR_SET_NEXT(heap, &obj->hdr, NULL);
53009 #if defined(DUK_USE_DOUBLE_LINKED_HEAP)
53010 	DUK_HEAPHDR_SET_PREV(heap, &obj->hdr, NULL);
53011 #endif
53012 #endif
53013 	DUK_ASSERT_HEAPHDR_LINKS(heap, &obj->hdr);
53014 	DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap, &obj->hdr);
53015 
53016 	/* obj->props is intentionally left as NULL, and duk_hobject_props.c must deal
53017 	 * with this properly.  This is intentional: empty objects consume a minimum
53018 	 * amount of memory.  Further, an initial allocation might fail and cause
53019 	 * 'obj' to "leak" (require a mark-and-sweep) since it is not reachable yet.
53020 	 */
53021 }
53022 
53023 DUK_LOCAL void *duk__hobject_alloc_init(duk_hthread *thr, duk_uint_t hobject_flags, duk_size_t size) {
53024 	void *res;
53025 
53026 	res = (void *) DUK_ALLOC_CHECKED_ZEROED(thr, size);
53027 	DUK_ASSERT(res != NULL);
53028 	duk__init_object_parts(thr->heap, hobject_flags, (duk_hobject *) res);
53029 	return res;
53030 }
53031 
53032 /*
53033  *  Allocate an duk_hobject.
53034  *
53035  *  The allocated object has no allocation for properties; the caller may
53036  *  want to force a resize if a desired size is known.
53037  *
53038  *  The allocated object has zero reference count and is not reachable.
53039  *  The caller MUST make the object reachable and increase its reference
53040  *  count before invoking any operation that might require memory allocation.
53041  */
53042 
53043 DUK_INTERNAL duk_hobject *duk_hobject_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53044 	duk_hobject *res;
53045 
53046 	DUK_ASSERT(heap != NULL);
53047 
53048 	/* different memory layout, alloc size, and init */
53049 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_COMPFUNC) == 0);
53050 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_NATFUNC) == 0);
53051 	DUK_ASSERT((hobject_flags & DUK_HOBJECT_FLAG_BOUNDFUNC) == 0);
53052 
53053 	res = (duk_hobject *) DUK_ALLOC_ZEROED(heap, sizeof(duk_hobject));
53054 	if (DUK_UNLIKELY(res == NULL)) {
53055 		return NULL;
53056 	}
53057 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53058 
53059 	duk__init_object_parts(heap, hobject_flags, res);
53060 
53061 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(res));
53062 	return res;
53063 }
53064 
53065 DUK_INTERNAL duk_hobject *duk_hobject_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53066 	duk_hobject *res;
53067 
53068 	res = (duk_hobject *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobject));
53069 	return res;
53070 }
53071 
53072 DUK_INTERNAL duk_hcompfunc *duk_hcompfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53073 	duk_hcompfunc *res;
53074 
53075 	res = (duk_hcompfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hcompfunc));
53076 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53077 #if defined(DUK_USE_HEAPPTR16)
53078 	/* NULL pointer is required to encode to zero, so memset is enough. */
53079 #else
53080 	res->data = NULL;
53081 	res->funcs = NULL;
53082 	res->bytecode = NULL;
53083 #endif
53084 	res->lex_env = NULL;
53085 	res->var_env = NULL;
53086 #endif
53087 
53088 	return res;
53089 }
53090 
53091 DUK_INTERNAL duk_hnatfunc *duk_hnatfunc_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53092 	duk_hnatfunc *res;
53093 
53094 	res = (duk_hnatfunc *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hnatfunc));
53095 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53096 	res->func = NULL;
53097 #endif
53098 
53099 	return res;
53100 }
53101 
53102 DUK_INTERNAL duk_hboundfunc *duk_hboundfunc_alloc(duk_heap *heap, duk_uint_t hobject_flags) {
53103 	duk_hboundfunc *res;
53104 
53105 	res = (duk_hboundfunc *) DUK_ALLOC(heap, sizeof(duk_hboundfunc));
53106 	if (!res) {
53107 		return NULL;
53108 	}
53109 	duk_memzero(res, sizeof(duk_hboundfunc));
53110 
53111 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53112 
53113 	DUK_TVAL_SET_UNDEFINED(&res->target);
53114 	DUK_TVAL_SET_UNDEFINED(&res->this_binding);
53115 
53116 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53117 	res->args = NULL;
53118 #endif
53119 
53120 	return res;
53121 }
53122 
53123 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53124 DUK_INTERNAL duk_hbufobj *duk_hbufobj_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53125 	duk_hbufobj *res;
53126 
53127 	res = (duk_hbufobj *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hbufobj));
53128 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53129 	res->buf = NULL;
53130 	res->buf_prop = NULL;
53131 #endif
53132 
53133 	DUK_ASSERT_HBUFOBJ_VALID(res);
53134 	return res;
53135 }
53136 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53137 
53138 /* Allocate a new thread.
53139  *
53140  * Leaves the built-ins array uninitialized.  The caller must either
53141  * initialize a new global context or share existing built-ins from
53142  * another thread.
53143  */
53144 DUK_INTERNAL duk_hthread *duk_hthread_alloc_unchecked(duk_heap *heap, duk_uint_t hobject_flags) {
53145 	duk_hthread *res;
53146 
53147 	res = (duk_hthread *) DUK_ALLOC(heap, sizeof(duk_hthread));
53148 	if (DUK_UNLIKELY(res == NULL)) {
53149 		return NULL;
53150 	}
53151 	duk_memzero(res, sizeof(duk_hthread));
53152 
53153 	duk__init_object_parts(heap, hobject_flags, &res->obj);
53154 
53155 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53156 	res->ptr_curr_pc = NULL;
53157 	res->heap = NULL;
53158 	res->valstack = NULL;
53159 	res->valstack_end = NULL;
53160 	res->valstack_alloc_end = NULL;
53161 	res->valstack_bottom = NULL;
53162 	res->valstack_top = NULL;
53163 	res->callstack_curr = NULL;
53164 	res->resumer = NULL;
53165 	res->compile_ctx = NULL,
53166 #if defined(DUK_USE_HEAPPTR16)
53167 	res->strs16 = NULL;
53168 #else
53169 	res->strs = NULL;
53170 #endif
53171 	{
53172 		duk_small_uint_t i;
53173 		for (i = 0; i < DUK_NUM_BUILTINS; i++) {
53174 			res->builtins[i] = NULL;
53175 		}
53176 	}
53177 #endif
53178 	/* When nothing is running, API calls are in non-strict mode. */
53179 	DUK_ASSERT(res->strict == 0);
53180 
53181 	res->heap = heap;
53182 
53183 	/* XXX: Any reason not to merge duk_hthread_alloc.c here? */
53184 	return res;
53185 }
53186 
53187 DUK_INTERNAL duk_hthread *duk_hthread_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53188 	duk_hthread *res;
53189 
53190 	res = duk_hthread_alloc_unchecked(thr->heap, hobject_flags);
53191 	if (res == NULL) {
53192 		DUK_ERROR_ALLOC_FAILED(thr);
53193 		DUK_WO_NORETURN(return NULL;);
53194 	}
53195 	return res;
53196 }
53197 
53198 DUK_INTERNAL duk_harray *duk_harray_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53199 	duk_harray *res;
53200 
53201 	res = (duk_harray *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_harray));
53202 
53203 	DUK_ASSERT(res->length == 0);
53204 
53205 	return res;
53206 }
53207 
53208 DUK_INTERNAL duk_hdecenv *duk_hdecenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53209 	duk_hdecenv *res;
53210 
53211 	res = (duk_hdecenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hdecenv));
53212 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53213 	res->thread = NULL;
53214 	res->varmap = NULL;
53215 #endif
53216 
53217 	DUK_ASSERT(res->thread == NULL);
53218 	DUK_ASSERT(res->varmap == NULL);
53219 	DUK_ASSERT(res->regbase_byteoff == 0);
53220 
53221 	return res;
53222 }
53223 
53224 DUK_INTERNAL duk_hobjenv *duk_hobjenv_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53225 	duk_hobjenv *res;
53226 
53227 	res = (duk_hobjenv *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hobjenv));
53228 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
53229 	res->target = NULL;
53230 #endif
53231 
53232 	DUK_ASSERT(res->target == NULL);
53233 
53234 	return res;
53235 }
53236 
53237 DUK_INTERNAL duk_hproxy *duk_hproxy_alloc(duk_hthread *thr, duk_uint_t hobject_flags) {
53238 	duk_hproxy *res;
53239 
53240 	res = (duk_hproxy *) duk__hobject_alloc_init(thr, hobject_flags, sizeof(duk_hproxy));
53241 
53242 	/* Leave ->target and ->handler uninitialized, as caller will always
53243 	 * explicitly initialize them before any side effects are possible.
53244 	 */
53245 
53246 	return res;
53247 }
53248 #line 1 "duk_hobject_enum.c"
53249 /*
53250  *  Object enumeration support.
53251  *
53252  *  Creates an internal enumeration state object to be used e.g. with for-in
53253  *  enumeration.  The state object contains a snapshot of target object keys
53254  *  and internal control state for enumeration.  Enumerator flags allow caller
53255  *  to e.g. request internal/non-enumerable properties, and to enumerate only
53256  *  "own" properties.
53257  *
53258  *  Also creates the result value for e.g. Object.keys() based on the same
53259  *  internal structure.
53260  *
53261  *  This snapshot-based enumeration approach is used to simplify enumeration:
53262  *  non-snapshot-based approaches are difficult to reconcile with mutating
53263  *  the enumeration target, running multiple long-lived enumerators at the
53264  *  same time, garbage collection details, etc.  The downside is that the
53265  *  enumerator object is memory inefficient especially for iterating arrays.
53266  */
53267 
53268 /* #include duk_internal.h -> already included */
53269 
53270 /* XXX: identify enumeration target with an object index (not top of stack) */
53271 
53272 /* First enumerated key index in enumerator object, must match exactly the
53273  * number of control properties inserted to the enumerator.
53274  */
53275 #define DUK__ENUM_START_INDEX  2
53276 
53277 /* Current implementation suffices for ES2015 for now because there's no symbol
53278  * sorting, so commented out for now.
53279  */
53280 
53281 /*
53282  *  Helper to sort enumeration keys using a callback for pairwise duk_hstring
53283  *  comparisons.  The keys are in the enumeration object entry part, starting
53284  *  from DUK__ENUM_START_INDEX, and the entry part is dense.  Entry part values
53285  *  are all "true", e.g. "1" -> true, "3" -> true, "foo" -> true, "2" -> true,
53286  *  so it suffices to just switch keys without switching values.
53287  *
53288  *  ES2015 [[OwnPropertyKeys]] enumeration order for ordinary objects:
53289  *  (1) array indices in ascending order,
53290  *  (2) non-array-index keys in insertion order, and
53291  *  (3) symbols in insertion order.
53292  *  http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys.
53293  *
53294  *  This rule is applied to "own properties" at each inheritance level;
53295  *  non-duplicate parent keys always follow child keys.  For example,
53296  *  an inherited array index will enumerate -after- a symbol in the
53297  *  child.
53298  *
53299  *  Insertion sort is used because (1) it's simple and compact, (2) works
53300  *  in-place, (3) minimizes operations if data is already nearly sorted,
53301  *  (4) doesn't reorder elements considered equal.
53302  *  http://en.wikipedia.org/wiki/Insertion_sort
53303  */
53304 
53305 /* Sort key, must hold array indices, "not array index" marker, and one more
53306  * higher value for symbols.
53307  */
53308 #if !defined(DUK_USE_SYMBOL_BUILTIN)
53309 typedef duk_uint32_t duk__sort_key_t;
53310 #elif defined(DUK_USE_64BIT_OPS)
53311 typedef duk_uint64_t duk__sort_key_t;
53312 #else
53313 typedef duk_double_t duk__sort_key_t;
53314 #endif
53315 
53316 /* Get sort key for a duk_hstring. */
53317 DUK_LOCAL duk__sort_key_t duk__hstring_sort_key(duk_hstring *x) {
53318 	duk__sort_key_t val;
53319 
53320 	/* For array indices [0,0xfffffffe] use the array index as is.
53321 	 * For strings, use 0xffffffff, the marker 'arridx' already in
53322 	 * duk_hstring.  For symbols, any value above 0xffffffff works,
53323 	 * as long as it is the same for all symbols; currently just add
53324 	 * the masked flag field into the arridx temporary.
53325 	 */
53326 	DUK_ASSERT(x != NULL);
53327 	DUK_ASSERT(!DUK_HSTRING_HAS_SYMBOL(x) || DUK_HSTRING_GET_ARRIDX_FAST(x) == DUK_HSTRING_NO_ARRAY_INDEX);
53328 
53329 	val = (duk__sort_key_t) DUK_HSTRING_GET_ARRIDX_FAST(x);
53330 
53331 #if defined(DUK_USE_SYMBOL_BUILTIN)
53332 	val = val + (duk__sort_key_t) (DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) x) & DUK_HSTRING_FLAG_SYMBOL);
53333 #endif
53334 
53335 	return (duk__sort_key_t) val;
53336 }
53337 
53338 /* Insert element 'b' after element 'a'? */
53339 DUK_LOCAL duk_bool_t duk__sort_compare_es6(duk_hstring *a, duk_hstring *b, duk__sort_key_t val_b) {
53340 	duk__sort_key_t val_a;
53341 
53342 	DUK_ASSERT(a != NULL);
53343 	DUK_ASSERT(b != NULL);
53344 	DUK_UNREF(b);  /* Not actually needed now, val_b suffices. */
53345 
53346 	val_a = duk__hstring_sort_key(a);
53347 
53348 	if (val_a > val_b) {
53349 		return 0;
53350 	} else {
53351 		return 1;
53352 	}
53353 }
53354 
53355 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) {
53356 	duk_hstring **keys;
53357 	duk_int_fast32_t idx;
53358 
53359 	DUK_ASSERT(h_obj != NULL);
53360 	DUK_ASSERT(idx_start >= DUK__ENUM_START_INDEX);
53361 	DUK_ASSERT(idx_end >= idx_start);
53362 	DUK_UNREF(thr);
53363 
53364 	if (idx_end <= idx_start + 1) {
53365 		return;  /* Zero or one element(s). */
53366 	}
53367 
53368 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, h_obj);
53369 
53370 	for (idx = idx_start + 1; idx < idx_end; idx++) {
53371 		duk_hstring *h_curr;
53372 		duk_int_fast32_t idx_insert;
53373 		duk__sort_key_t val_curr;
53374 
53375 		h_curr = keys[idx];
53376 		DUK_ASSERT(h_curr != NULL);
53377 
53378 		/* Scan backwards for insertion place.  This works very well
53379 		 * when the elements are nearly in order which is the common
53380 		 * (and optimized for) case.
53381 		 */
53382 
53383 		val_curr = duk__hstring_sort_key(h_curr);  /* Remains same during scanning. */
53384 		for (idx_insert = idx - 1; idx_insert >= idx_start; idx_insert--) {
53385 			duk_hstring *h_insert;
53386 			h_insert = keys[idx_insert];
53387 			DUK_ASSERT(h_insert != NULL);
53388 
53389 			if (duk__sort_compare_es6(h_insert, h_curr, val_curr)) {
53390 				break;
53391 			}
53392 		}
53393 		/* If we're out of indices, idx_insert == idx_start - 1 and idx_insert++
53394 		 * brings us back to idx_start.
53395 		 */
53396 		idx_insert++;
53397 		DUK_ASSERT(idx_insert >= 0 && idx_insert <= idx);
53398 
53399 		/*        .-- p_insert   .-- p_curr
53400 		 *        v              v
53401 		 *  | ... | insert | ... | curr
53402 		 */
53403 
53404 		/* This could also done when the keys are in order, i.e.
53405 		 * idx_insert == idx.  The result would be an unnecessary
53406 		 * memmove() but we use an explicit check because the keys
53407 		 * are very often in order already.
53408 		 */
53409 		if (idx != idx_insert) {
53410 			duk_memmove((void *) (keys + idx_insert + 1),
53411 			            (const void *) (keys + idx_insert),
53412 			            ((size_t) (idx - idx_insert) * sizeof(duk_hstring *)));
53413 			keys[idx_insert] = h_curr;
53414 		}
53415 	}
53416 }
53417 
53418 /*
53419  *  Create an internal enumerator object E, which has its keys ordered
53420  *  to match desired enumeration ordering.  Also initialize internal control
53421  *  properties for enumeration.
53422  *
53423  *  Note: if an array was used to hold enumeration keys instead, an array
53424  *  scan would be needed to eliminate duplicates found in the prototype chain.
53425  */
53426 
53427 DUK_LOCAL void duk__add_enum_key(duk_hthread *thr, duk_hstring *k) {
53428 	/* 'k' may be unreachable on entry so must push without any
53429 	 * potential for GC.
53430 	 */
53431 	duk_push_hstring(thr, k);
53432 	duk_push_true(thr);
53433 	duk_put_prop(thr, -3);
53434 }
53435 
53436 DUK_LOCAL void duk__add_enum_key_stridx(duk_hthread *thr, duk_small_uint_t stridx) {
53437 	duk__add_enum_key(thr, DUK_HTHREAD_GET_STRING(thr, stridx));
53438 }
53439 
53440 DUK_INTERNAL void duk_hobject_enumerator_create(duk_hthread *thr, duk_small_uint_t enum_flags) {
53441 	duk_hobject *enum_target;
53442 	duk_hobject *curr;
53443 	duk_hobject *res;
53444 #if defined(DUK_USE_ES6_PROXY)
53445 	duk_hobject *h_proxy_target;
53446 	duk_hobject *h_proxy_handler;
53447 	duk_hobject *h_trap_result;
53448 #endif
53449 	duk_uint_fast32_t i, len;  /* used for array, stack, and entry indices */
53450 	duk_uint_fast32_t sort_start_index;
53451 
53452 	DUK_ASSERT(thr != NULL);
53453 
53454 	enum_target = duk_require_hobject(thr, -1);
53455 	DUK_ASSERT(enum_target != NULL);
53456 
53457 	duk_push_bare_object(thr);
53458 	res = duk_known_hobject(thr, -1);
53459 
53460 	/* [enum_target res] */
53461 
53462 	/* Target must be stored so that we can recheck whether or not
53463 	 * keys still exist when we enumerate.  This is not done if the
53464 	 * enumeration result comes from a proxy trap as there is no
53465 	 * real object to check against.
53466 	 */
53467 	duk_push_hobject(thr, enum_target);
53468 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET);
53469 
53470 	/* Initialize index so that we skip internal control keys. */
53471 	duk_push_int(thr, DUK__ENUM_START_INDEX);
53472 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
53473 
53474 	/*
53475 	 *  Proxy object handling
53476 	 */
53477 
53478 #if defined(DUK_USE_ES6_PROXY)
53479 	if (DUK_LIKELY((enum_flags & DUK_ENUM_NO_PROXY_BEHAVIOR) != 0)) {
53480 		goto skip_proxy;
53481 	}
53482 	if (DUK_LIKELY(!duk_hobject_proxy_check(enum_target,
53483 	                                        &h_proxy_target,
53484 	                                        &h_proxy_handler))) {
53485 		goto skip_proxy;
53486 	}
53487 
53488 	/* XXX: share code with Object.keys() Proxy handling */
53489 
53490 	/* In ES2015 for-in invoked the "enumerate" trap; in ES2016 "enumerate"
53491 	 * has been obsoleted and "ownKeys" is used instead.
53492 	 */
53493 	DUK_DDD(DUK_DDDPRINT("proxy enumeration"));
53494 	duk_push_hobject(thr, h_proxy_handler);
53495 	if (!duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_OWN_KEYS)) {
53496 		/* No need to replace the 'enum_target' value in stack, only the
53497 		 * enum_target reference.  This also ensures that the original
53498 		 * enum target is reachable, which keeps the proxy and the proxy
53499 		 * target reachable.  We do need to replace the internal _Target.
53500 		 */
53501 		DUK_DDD(DUK_DDDPRINT("no ownKeys trap, enumerate proxy target instead"));
53502 		DUK_DDD(DUK_DDDPRINT("h_proxy_target=%!O", (duk_heaphdr *) h_proxy_target));
53503 		enum_target = h_proxy_target;
53504 
53505 		duk_push_hobject(thr, enum_target);  /* -> [ ... enum_target res handler undefined target ] */
53506 		duk_put_prop_stridx_short(thr, -4, DUK_STRIDX_INT_TARGET);
53507 
53508 		duk_pop_2(thr);  /* -> [ ... enum_target res ] */
53509 		goto skip_proxy;
53510 	}
53511 
53512 	/* [ ... enum_target res handler trap ] */
53513 	duk_insert(thr, -2);
53514 	duk_push_hobject(thr, h_proxy_target);    /* -> [ ... enum_target res trap handler target ] */
53515 	duk_call_method(thr, 1 /*nargs*/);        /* -> [ ... enum_target res trap_result ] */
53516 	h_trap_result = duk_require_hobject(thr, -1);
53517 	DUK_UNREF(h_trap_result);
53518 
53519 	duk_proxy_ownkeys_postprocess(thr, h_proxy_target, enum_flags);
53520 	/* -> [ ... enum_target res trap_result keys_array ] */
53521 
53522 	/* Copy cleaned up trap result keys into the enumerator object. */
53523 	/* XXX: result is a dense array; could make use of that. */
53524 	DUK_ASSERT(duk_is_array(thr, -1));
53525 	len = (duk_uint_fast32_t) duk_get_length(thr, -1);
53526 	for (i = 0; i < len; i++) {
53527 		(void) duk_get_prop_index(thr, -1, (duk_uarridx_t) i);
53528 		DUK_ASSERT(duk_is_string(thr, -1));  /* postprocess cleaned up */
53529 		/* [ ... enum_target res trap_result keys_array val ] */
53530 		duk_push_true(thr);
53531 		/* [ ... enum_target res trap_result keys_array val true ] */
53532 		duk_put_prop(thr, -5);
53533 	}
53534 	/* [ ... enum_target res trap_result keys_array ] */
53535 	duk_pop_2(thr);
53536 	duk_remove_m2(thr);
53537 
53538 	/* [ ... res ] */
53539 
53540 	/* The internal _Target property is kept pointing to the original
53541 	 * enumeration target (the proxy object), so that the enumerator
53542 	 * 'next' operation can read property values if so requested.  The
53543 	 * fact that the _Target is a proxy disables key existence check
53544 	 * during enumeration.
53545 	 */
53546 	DUK_DDD(DUK_DDDPRINT("proxy enumeration, final res: %!O", (duk_heaphdr *) res));
53547 	goto compact_and_return;
53548 
53549  skip_proxy:
53550 #endif  /* DUK_USE_ES6_PROXY */
53551 
53552 	curr = enum_target;
53553 	sort_start_index = DUK__ENUM_START_INDEX;
53554 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(res) == DUK__ENUM_START_INDEX);
53555 	while (curr) {
53556 		duk_uint_fast32_t sort_end_index;
53557 #if !defined(DUK_USE_PREFER_SIZE)
53558 		duk_bool_t need_sort = 0;
53559 #endif
53560 
53561 		/* Enumeration proceeds by inheritance level.  Virtual
53562 		 * properties need to be handled specially, followed by
53563 		 * array part, and finally entry part.
53564 		 *
53565 		 * If there are array index keys in the entry part or any
53566 		 * other risk of the ES2015 [[OwnPropertyKeys]] order being
53567 		 * violated, need_sort is set and an explicit ES2015 sort is
53568 		 * done for the inheritance level.
53569 		 */
53570 
53571 		/* XXX: inheriting from proxy */
53572 
53573 		/*
53574 		 *  Virtual properties.
53575 		 *
53576 		 *  String and buffer indices are virtual and always enumerable,
53577 		 *  'length' is virtual and non-enumerable.  Array and arguments
53578 		 *  object props have special behavior but are concrete.
53579 		 *
53580 		 *  String and buffer objects don't have an array part so as long
53581 		 *  as virtual array index keys are enumerated first, we don't
53582 		 *  need to set need_sort.
53583 		 */
53584 
53585 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53586 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr) || DUK_HOBJECT_IS_BUFOBJ(curr)) {
53587 #else
53588 		if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
53589 #endif
53590 			duk_bool_t have_length = 1;
53591 
53592 			/* String and buffer enumeration behavior is identical now,
53593 			 * so use shared handler.
53594 			 */
53595 			if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(curr)) {
53596 				duk_hstring *h_val;
53597 				h_val = duk_hobject_get_internal_value_string(thr->heap, curr);
53598 				DUK_ASSERT(h_val != NULL);  /* string objects must not created without internal value */
53599 				len = (duk_uint_fast32_t) DUK_HSTRING_GET_CHARLEN(h_val);
53600 			}
53601 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
53602 			else {
53603 				duk_hbufobj *h_bufobj;
53604 				DUK_ASSERT(DUK_HOBJECT_IS_BUFOBJ(curr));
53605 				h_bufobj = (duk_hbufobj *) curr;
53606 
53607 				if (h_bufobj == NULL || !h_bufobj->is_typedarray) {
53608 					/* Zero length seems like a good behavior for neutered buffers.
53609 					 * ArrayBuffer (non-view) and DataView don't have index properties
53610 					 * or .length property.
53611 					 */
53612 					len = 0;
53613 					have_length = 0;
53614 				} else {
53615 					/* There's intentionally no check for
53616 					 * current underlying buffer length.
53617 					 */
53618 					len = (duk_uint_fast32_t) (h_bufobj->length >> h_bufobj->shift);
53619 				}
53620 			}
53621 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
53622 
53623 			for (i = 0; i < len; i++) {
53624 				duk_hstring *k;
53625 
53626 				/* This is a bit fragile: the string is not
53627 				 * reachable until it is pushed by the helper.
53628 				 */
53629 				k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);
53630 				DUK_ASSERT(k);
53631 
53632 				duk__add_enum_key(thr, k);
53633 
53634 				/* [enum_target res] */
53635 			}
53636 
53637 			/* 'length' and other virtual properties are not
53638 			 * enumerable, but are included if non-enumerable
53639 			 * properties are requested.
53640 			 */
53641 
53642 			if (have_length && (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE)) {
53643 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
53644 			}
53645 		}
53646 
53647 		/*
53648 		 *  Array part
53649 		 */
53650 
53651 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ASIZE(curr); i++) {
53652 			duk_hstring *k;
53653 			duk_tval *tv;
53654 
53655 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, curr, i);
53656 			if (DUK_TVAL_IS_UNUSED(tv)) {
53657 				continue;
53658 			}
53659 			k = duk_heap_strtable_intern_u32_checked(thr, (duk_uint32_t) i);  /* Fragile reachability. */
53660 			DUK_ASSERT(k);
53661 
53662 			duk__add_enum_key(thr, k);
53663 
53664 			/* [enum_target res] */
53665 		}
53666 
53667 		if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(curr)) {
53668 			/* Array .length comes after numeric indices. */
53669 			if (enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) {
53670 				duk__add_enum_key_stridx(thr, DUK_STRIDX_LENGTH);
53671 			}
53672 		}
53673 
53674 		/*
53675 		 *  Entries part
53676 		 */
53677 
53678 		for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(curr); i++) {
53679 			duk_hstring *k;
53680 
53681 			k = DUK_HOBJECT_E_GET_KEY(thr->heap, curr, i);
53682 			if (!k) {
53683 				continue;
53684 			}
53685 			if (!(enum_flags & DUK_ENUM_INCLUDE_NONENUMERABLE) &&
53686 			    !DUK_HOBJECT_E_SLOT_IS_ENUMERABLE(thr->heap, curr, i)) {
53687 				continue;
53688 			}
53689 			if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(k))) {
53690 				if (!(enum_flags & DUK_ENUM_INCLUDE_HIDDEN) &&
53691 				    DUK_HSTRING_HAS_HIDDEN(k)) {
53692 					continue;
53693 				}
53694 				if (!(enum_flags & DUK_ENUM_INCLUDE_SYMBOLS)) {
53695 					continue;
53696 				}
53697 #if !defined(DUK_USE_PREFER_SIZE)
53698 				need_sort = 1;
53699 #endif
53700 			} else {
53701 				DUK_ASSERT(!DUK_HSTRING_HAS_HIDDEN(k));  /* would also have symbol flag */
53702 				if (enum_flags & DUK_ENUM_EXCLUDE_STRINGS) {
53703 					continue;
53704 				}
53705 			}
53706 			if (DUK_HSTRING_HAS_ARRIDX(k)) {
53707 				/* This in currently only possible if the
53708 				 * object has no array part: the array part
53709 				 * is exhaustive when it is present.
53710 				 */
53711 #if !defined(DUK_USE_PREFER_SIZE)
53712 				need_sort = 1;
53713 #endif
53714 			} else {
53715 				if (enum_flags & DUK_ENUM_ARRAY_INDICES_ONLY) {
53716 					continue;
53717 				}
53718 			}
53719 
53720 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, curr, i) ||
53721 			           !DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE_PTR(thr->heap, curr, i)->v));
53722 
53723 			duk__add_enum_key(thr, k);
53724 
53725 			/* [enum_target res] */
53726 		}
53727 
53728 		/* Sort enumerated keys according to ES2015 requirements for
53729 		 * the "inheritance level" just processed.  This is far from
53730 		 * optimal, ES2015 semantics could be achieved more efficiently
53731 		 * by handling array index string keys (and symbol keys)
53732 		 * specially above in effect doing the sort inline.
53733 		 *
53734 		 * Skip the sort if array index sorting is requested because
53735 		 * we must consider all keys, also inherited, so an explicit
53736 		 * sort is done for the whole result after we're done with the
53737 		 * prototype chain.
53738 		 *
53739 		 * Also skip the sort if need_sort == 0, i.e. we know for
53740 		 * certain that the enumerated order is already correct.
53741 		 */
53742 		sort_end_index = DUK_HOBJECT_GET_ENEXT(res);
53743 
53744 		if (!(enum_flags & DUK_ENUM_SORT_ARRAY_INDICES)) {
53745 #if defined(DUK_USE_PREFER_SIZE)
53746 			duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
53747 #else
53748 			if (need_sort) {
53749 				DUK_DDD(DUK_DDDPRINT("need to sort"));
53750 				duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) sort_start_index, (duk_int_fast32_t) sort_end_index);
53751 			} else {
53752 				DUK_DDD(DUK_DDDPRINT("no need to sort"));
53753 			}
53754 #endif
53755 		}
53756 
53757 		sort_start_index = sort_end_index;
53758 
53759 		if (enum_flags & DUK_ENUM_OWN_PROPERTIES_ONLY) {
53760 			break;
53761 		}
53762 
53763 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
53764 	}
53765 
53766 	/* [enum_target res] */
53767 
53768 	duk_remove_m2(thr);
53769 
53770 	/* [res] */
53771 
53772 	if (enum_flags & DUK_ENUM_SORT_ARRAY_INDICES) {
53773 		/* Some E5/E5.1 algorithms require that array indices are iterated
53774 		 * in a strictly ascending order.  This is the case for e.g.
53775 		 * Array.prototype.forEach() and JSON.stringify() PropertyList
53776 		 * handling.  The caller can request an explicit sort in these
53777 		 * cases.
53778 		 */
53779 
53780 		/* Sort to ES2015 order which works for pure array incides but
53781 		 * also for mixed keys.
53782 		 */
53783 		duk__sort_enum_keys_es6(thr, res, (duk_int_fast32_t) DUK__ENUM_START_INDEX, (duk_int_fast32_t) DUK_HOBJECT_GET_ENEXT(res));
53784 	}
53785 
53786 #if defined(DUK_USE_ES6_PROXY)
53787  compact_and_return:
53788 #endif
53789 	/* compact; no need to seal because object is internal */
53790 	duk_hobject_compact_props(thr, res);
53791 
53792 	DUK_DDD(DUK_DDDPRINT("created enumerator object: %!iT", (duk_tval *) duk_get_tval(thr, -1)));
53793 }
53794 
53795 /*
53796  *  Returns non-zero if a key and/or value was enumerated, and:
53797  *
53798  *   [enum] -> [key]        (get_value == 0)
53799  *   [enum] -> [key value]  (get_value == 1)
53800  *
53801  *  Returns zero without pushing anything on the stack otherwise.
53802  */
53803 DUK_INTERNAL duk_bool_t duk_hobject_enumerator_next(duk_hthread *thr, duk_bool_t get_value) {
53804 	duk_hobject *e;
53805 	duk_hobject *enum_target;
53806 	duk_hstring *res = NULL;
53807 	duk_uint_fast32_t idx;
53808 	duk_bool_t check_existence;
53809 
53810 	DUK_ASSERT(thr != NULL);
53811 
53812 	/* [... enum] */
53813 
53814 	e = duk_require_hobject(thr, -1);
53815 
53816 	/* XXX use get tval ptr, more efficient */
53817 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_NEXT);
53818 	idx = (duk_uint_fast32_t) duk_require_uint(thr, -1);
53819 	duk_pop(thr);
53820 	DUK_DDD(DUK_DDDPRINT("enumeration: index is: %ld", (long) idx));
53821 
53822 	/* Enumeration keys are checked against the enumeration target (to see
53823 	 * that they still exist).  In the proxy enumeration case _Target will
53824 	 * be the proxy, and checking key existence against the proxy is not
53825 	 * required (or sensible, as the keys may be fully virtual).
53826 	 */
53827 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_TARGET);
53828 	enum_target = duk_require_hobject(thr, -1);
53829 	DUK_ASSERT(enum_target != NULL);
53830 #if defined(DUK_USE_ES6_PROXY)
53831 	check_existence = (!DUK_HOBJECT_IS_PROXY(enum_target));
53832 #else
53833 	check_existence = 1;
53834 #endif
53835 	duk_pop(thr);  /* still reachable */
53836 
53837 	DUK_DDD(DUK_DDDPRINT("getting next enum value, enum_target=%!iO, enumerator=%!iT",
53838 	                     (duk_heaphdr *) enum_target, (duk_tval *) duk_get_tval(thr, -1)));
53839 
53840 	/* no array part */
53841 	for (;;) {
53842 		duk_hstring *k;
53843 
53844 		if (idx >= DUK_HOBJECT_GET_ENEXT(e)) {
53845 			DUK_DDD(DUK_DDDPRINT("enumeration: ran out of elements"));
53846 			break;
53847 		}
53848 
53849 		/* we know these because enum objects are internally created */
53850 		k = DUK_HOBJECT_E_GET_KEY(thr->heap, e, idx);
53851 		DUK_ASSERT(k != NULL);
53852 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, e, idx));
53853 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(&DUK_HOBJECT_E_GET_VALUE(thr->heap, e, idx).v));
53854 
53855 		idx++;
53856 
53857 		/* recheck that the property still exists */
53858 		if (check_existence && !duk_hobject_hasprop_raw(thr, enum_target, k)) {
53859 			DUK_DDD(DUK_DDDPRINT("property deleted during enumeration, skip"));
53860 			continue;
53861 		}
53862 
53863 		DUK_DDD(DUK_DDDPRINT("enumeration: found element, key: %!O", (duk_heaphdr *) k));
53864 		res = k;
53865 		break;
53866 	}
53867 
53868 	DUK_DDD(DUK_DDDPRINT("enumeration: updating next index to %ld", (long) idx));
53869 
53870 	duk_push_u32(thr, (duk_uint32_t) idx);
53871 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_INT_NEXT);
53872 
53873 	/* [... enum] */
53874 
53875 	if (res) {
53876 		duk_push_hstring(thr, res);
53877 		if (get_value) {
53878 			duk_push_hobject(thr, enum_target);
53879 			duk_dup_m2(thr);       /* -> [... enum key enum_target key] */
53880 			duk_get_prop(thr, -2); /* -> [... enum key enum_target val] */
53881 			duk_remove_m2(thr);    /* -> [... enum key val] */
53882 			duk_remove(thr, -3);   /* -> [... key val] */
53883 		} else {
53884 			duk_remove_m2(thr);    /* -> [... key] */
53885 		}
53886 		return 1;
53887 	} else {
53888 		duk_pop(thr);  /* -> [...] */
53889 		return 0;
53890 	}
53891 }
53892 
53893 /*
53894  *  Get enumerated keys in an ECMAScript array.  Matches Object.keys() behavior
53895  *  described in E5 Section 15.2.3.14.
53896  */
53897 
53898 DUK_INTERNAL duk_ret_t duk_hobject_get_enumerated_keys(duk_hthread *thr, duk_small_uint_t enum_flags) {
53899 	duk_hobject *e;
53900 	duk_hstring **keys;
53901 	duk_tval *tv;
53902 	duk_uint_fast32_t count;
53903 
53904 	DUK_ASSERT(thr != NULL);
53905 	DUK_ASSERT(duk_get_hobject(thr, -1) != NULL);
53906 
53907 	/* Create a temporary enumerator to get the (non-duplicated) key list;
53908 	 * the enumerator state is initialized without being needed, but that
53909 	 * has little impact.
53910 	 */
53911 
53912 	duk_hobject_enumerator_create(thr, enum_flags);
53913 	e = duk_known_hobject(thr, -1);
53914 
53915 	/* [enum_target enum res] */
53916 
53917 	/* Create dense result array to exact size. */
53918 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(e) >= DUK__ENUM_START_INDEX);
53919 	count = (duk_uint32_t) (DUK_HOBJECT_GET_ENEXT(e) - DUK__ENUM_START_INDEX);
53920 
53921 	/* XXX: uninit would be OK */
53922 	tv = duk_push_harray_with_size_outptr(thr, (duk_uint32_t) count);
53923 	DUK_ASSERT(count == 0 || tv != NULL);
53924 
53925 	/* Fill result array, no side effects. */
53926 
53927 	keys = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, e);
53928 	keys += DUK__ENUM_START_INDEX;
53929 
53930 	while (count-- > 0) {
53931 		duk_hstring *k;
53932 
53933 		k = *keys++;
53934 		DUK_ASSERT(k != NULL);  /* enumerator must have no keys deleted */
53935 
53936 		DUK_TVAL_SET_STRING(tv, k);
53937 		tv++;
53938 		DUK_HSTRING_INCREF(thr, k);
53939 	}
53940 
53941 	/* [enum_target enum res] */
53942 	duk_remove_m2(thr);
53943 
53944 	/* [enum_target res] */
53945 
53946 	return 1;  /* return 1 to allow callers to tail call */
53947 }
53948 
53949 /* automatic undefs */
53950 #undef DUK__ENUM_START_INDEX
53951 #line 1 "duk_hobject_misc.c"
53952 /*
53953  *  Misc support functions
53954  */
53955 
53956 /* #include duk_internal.h -> already included */
53957 
53958 DUK_INTERNAL duk_bool_t duk_hobject_prototype_chain_contains(duk_hthread *thr, duk_hobject *h, duk_hobject *p, duk_bool_t ignore_loop) {
53959 	duk_uint_t sanity;
53960 
53961 	DUK_ASSERT(thr != NULL);
53962 
53963 	/* False if the object is NULL or the prototype 'p' is NULL.
53964 	 * In particular, false if both are NULL (don't compare equal).
53965 	 */
53966 	if (h == NULL || p == NULL) {
53967 		return 0;
53968 	}
53969 
53970 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
53971 	do {
53972 		if (h == p) {
53973 			return 1;
53974 		}
53975 
53976 		if (sanity-- == 0) {
53977 			if (ignore_loop) {
53978 				break;
53979 			} else {
53980 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
53981 				DUK_WO_NORETURN(return 0;);
53982 			}
53983 		}
53984 		h = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
53985 	} while (h);
53986 
53987 	return 0;
53988 }
53989 
53990 DUK_INTERNAL void duk_hobject_set_prototype_updref(duk_hthread *thr, duk_hobject *h, duk_hobject *p) {
53991 #if defined(DUK_USE_REFERENCE_COUNTING)
53992 	duk_hobject *tmp;
53993 
53994 	DUK_ASSERT(h);
53995 	tmp = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
53996 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
53997 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, p);  /* avoid problems if p == h->prototype */
53998 	DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
53999 #else
54000 	DUK_ASSERT(h);
54001 	DUK_UNREF(thr);
54002 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, h, p);
54003 #endif
54004 }
54005 #line 1 "duk_hobject_pc2line.c"
54006 /*
54007  *  Helpers for creating and querying pc2line debug data, which
54008  *  converts a bytecode program counter to a source line number.
54009  *
54010  *  The run-time pc2line data is bit-packed, and documented in:
54011  *
54012  *    doc/function-objects.rst
54013  */
54014 
54015 /* #include duk_internal.h -> already included */
54016 
54017 #if defined(DUK_USE_PC2LINE)
54018 
54019 /* Generate pc2line data for an instruction sequence, leaving a buffer on stack top. */
54020 DUK_INTERNAL void duk_hobject_pc2line_pack(duk_hthread *thr, duk_compiler_instr *instrs, duk_uint_fast32_t length) {
54021 	duk_hbuffer_dynamic *h_buf;
54022 	duk_bitencoder_ctx be_ctx_alloc;
54023 	duk_bitencoder_ctx *be_ctx = &be_ctx_alloc;
54024 	duk_uint32_t *hdr;
54025 	duk_size_t new_size;
54026 	duk_uint_fast32_t num_header_entries;
54027 	duk_uint_fast32_t curr_offset;
54028 	duk_int_fast32_t curr_line, next_line, diff_line;
54029 	duk_uint_fast32_t curr_pc;
54030 	duk_uint_fast32_t hdr_index;
54031 
54032 	DUK_ASSERT(length <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
54033 
54034 	num_header_entries = (length + DUK_PC2LINE_SKIP - 1) / DUK_PC2LINE_SKIP;
54035 	curr_offset = (duk_uint_fast32_t) (sizeof(duk_uint32_t) + num_header_entries * sizeof(duk_uint32_t) * 2);
54036 
54037 	duk_push_dynamic_buffer(thr, (duk_size_t) curr_offset);
54038 	h_buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
54039 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(h_buf) && !DUK_HBUFFER_HAS_EXTERNAL(h_buf));
54040 
54041 	hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54042 	DUK_ASSERT(hdr != NULL);
54043 	hdr[0] = (duk_uint32_t) length;  /* valid pc range is [0, length[ */
54044 
54045 	curr_pc = 0U;
54046 	while (curr_pc < length) {
54047 		new_size = (duk_size_t) (curr_offset + DUK_PC2LINE_MAX_DIFF_LENGTH);
54048 		duk_hbuffer_resize(thr, h_buf, new_size);
54049 
54050 		hdr = (duk_uint32_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, h_buf);
54051 		DUK_ASSERT(hdr != NULL);
54052 		DUK_ASSERT(curr_pc < length);
54053 		hdr_index = 1 + (curr_pc / DUK_PC2LINE_SKIP) * 2;
54054 		curr_line = (duk_int_fast32_t) instrs[curr_pc].line;
54055 		hdr[hdr_index + 0] = (duk_uint32_t) curr_line;
54056 		hdr[hdr_index + 1] = (duk_uint32_t) curr_offset;
54057 
54058 #if 0
54059 		DUK_DDD(DUK_DDDPRINT("hdr[%ld]: pc=%ld line=%ld offset=%ld",
54060 		                     (long) (curr_pc / DUK_PC2LINE_SKIP),
54061 		                     (long) curr_pc,
54062 		                     (long) hdr[hdr_index + 0],
54063 		                     (long) hdr[hdr_index + 1]));
54064 #endif
54065 
54066 		duk_memzero(be_ctx, sizeof(*be_ctx));
54067 		be_ctx->data = ((duk_uint8_t *) hdr) + curr_offset;
54068 		be_ctx->length = (duk_size_t) DUK_PC2LINE_MAX_DIFF_LENGTH;
54069 
54070 		for (;;) {
54071 			curr_pc++;
54072 			if ( ((curr_pc % DUK_PC2LINE_SKIP) == 0) ||  /* end of diff run */
54073 			     (curr_pc >= length) ) {                 /* end of bytecode */
54074 				break;
54075 			}
54076 			DUK_ASSERT(curr_pc < length);
54077 			next_line = (duk_int32_t) instrs[curr_pc].line;
54078 			diff_line = next_line - curr_line;
54079 
54080 #if 0
54081 			DUK_DDD(DUK_DDDPRINT("curr_line=%ld, next_line=%ld -> diff_line=%ld",
54082 			                     (long) curr_line, (long) next_line, (long) diff_line));
54083 #endif
54084 
54085 			if (diff_line == 0) {
54086 				/* 0 */
54087 				duk_be_encode(be_ctx, 0, 1);
54088 			} else if (diff_line >= 1 && diff_line <= 4) {
54089 				/* 1 0 <2 bits> */
54090 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x02 << 2) + (diff_line - 1)), 4);
54091 			} else if (diff_line >= -0x80 && diff_line <= 0x7f) {
54092 				/* 1 1 0 <8 bits> */
54093 				DUK_ASSERT(diff_line + 0x80 >= 0 && diff_line + 0x80 <= 0xff);
54094 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x06 << 8) + (diff_line + 0x80)), 11);
54095 			} else {
54096 				/* 1 1 1 <32 bits>
54097 				 * Encode in two parts to avoid bitencode 24-bit limitation
54098 				 */
54099 				duk_be_encode(be_ctx, (duk_uint32_t) ((0x07 << 16) + ((next_line >> 16) & 0xffff)), 19);
54100 				duk_be_encode(be_ctx, (duk_uint32_t) (next_line & 0xffff), 16);
54101 			}
54102 
54103 			curr_line = next_line;
54104 		}
54105 
54106 		duk_be_finish(be_ctx);
54107 		DUK_ASSERT(!be_ctx->truncated);
54108 
54109 		/* be_ctx->offset == length of encoded bitstream */
54110 		curr_offset += (duk_uint_fast32_t) be_ctx->offset;
54111 	}
54112 
54113 	/* compact */
54114 	new_size = (duk_size_t) curr_offset;
54115 	duk_hbuffer_resize(thr, h_buf, new_size);
54116 
54117 	(void) duk_to_fixed_buffer(thr, -1, NULL);
54118 
54119 	DUK_DDD(DUK_DDDPRINT("final pc2line data: pc_limit=%ld, length=%ld, %lf bits/opcode --> %!ixT",
54120 	                     (long) length, (long) new_size, (double) new_size * 8.0 / (double) length,
54121 	                     (duk_tval *) duk_get_tval(thr, -1)));
54122 }
54123 
54124 /* PC is unsigned.  If caller does PC arithmetic and gets a negative result,
54125  * it will map to a large PC which is out of bounds and causes a zero to be
54126  * returned.
54127  */
54128 DUK_LOCAL duk_uint_fast32_t duk__hobject_pc2line_query_raw(duk_hthread *thr, duk_hbuffer_fixed *buf, duk_uint_fast32_t pc) {
54129 	duk_bitdecoder_ctx bd_ctx_alloc;
54130 	duk_bitdecoder_ctx *bd_ctx = &bd_ctx_alloc;
54131 	duk_uint32_t *hdr;
54132 	duk_uint_fast32_t start_offset;
54133 	duk_uint_fast32_t pc_limit;
54134 	duk_uint_fast32_t hdr_index;
54135 	duk_uint_fast32_t pc_base;
54136 	duk_uint_fast32_t n;
54137 	duk_uint_fast32_t curr_line;
54138 
54139 	DUK_ASSERT(buf != NULL);
54140 	DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) buf) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) buf));
54141 	DUK_UNREF(thr);
54142 
54143 	/*
54144 	 *  Use the index in the header to find the right starting point
54145 	 */
54146 
54147 	hdr_index = pc / DUK_PC2LINE_SKIP;
54148 	pc_base = hdr_index * DUK_PC2LINE_SKIP;
54149 	n = pc - pc_base;
54150 
54151 	if (DUK_HBUFFER_FIXED_GET_SIZE(buf) <= sizeof(duk_uint32_t)) {
54152 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: buffer is smaller than minimal header"));
54153 		goto pc2line_error;
54154 	}
54155 
54156 	hdr = (duk_uint32_t *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, buf);
54157 	pc_limit = hdr[0];
54158 	if (pc >= pc_limit) {
54159 		/* Note: pc is unsigned and cannot be negative */
54160 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: pc out of bounds (pc=%ld, limit=%ld)",
54161 		                   (long) pc, (long) pc_limit));
54162 		goto pc2line_error;
54163 	}
54164 
54165 	curr_line = hdr[1 + hdr_index * 2];
54166 	start_offset = hdr[1 + hdr_index * 2 + 1];
54167 	if ((duk_size_t) start_offset > DUK_HBUFFER_FIXED_GET_SIZE(buf)) {
54168 		DUK_DD(DUK_DDPRINT("pc2line lookup failed: start_offset out of bounds (start_offset=%ld, buffer_size=%ld)",
54169 		                   (long) start_offset, (long) DUK_HBUFFER_GET_SIZE((duk_hbuffer *) buf)));
54170 		goto pc2line_error;
54171 	}
54172 
54173 	/*
54174 	 *  Iterate the bitstream (line diffs) until PC is reached
54175 	 */
54176 
54177 	duk_memzero(bd_ctx, sizeof(*bd_ctx));
54178 	bd_ctx->data = ((duk_uint8_t *) hdr) + start_offset;
54179 	bd_ctx->length = (duk_size_t) (DUK_HBUFFER_FIXED_GET_SIZE(buf) - start_offset);
54180 
54181 #if 0
54182 	DUK_DDD(DUK_DDDPRINT("pc2line lookup: pc=%ld -> hdr_index=%ld, pc_base=%ld, n=%ld, start_offset=%ld",
54183 	                     (long) pc, (long) hdr_index, (long) pc_base, (long) n, (long) start_offset));
54184 #endif
54185 
54186 	while (n > 0) {
54187 #if 0
54188 		DUK_DDD(DUK_DDDPRINT("lookup: n=%ld, curr_line=%ld", (long) n, (long) curr_line));
54189 #endif
54190 
54191 		if (duk_bd_decode_flag(bd_ctx)) {
54192 			if (duk_bd_decode_flag(bd_ctx)) {
54193 				if (duk_bd_decode_flag(bd_ctx)) {
54194 					/* 1 1 1 <32 bits> */
54195 					duk_uint_fast32_t t;
54196 					t = duk_bd_decode(bd_ctx, 16);  /* workaround: max nbits = 24 now */
54197 					t = (t << 16) + duk_bd_decode(bd_ctx, 16);
54198 					curr_line = t;
54199 				} else {
54200 					/* 1 1 0 <8 bits> */
54201 					duk_uint_fast32_t t;
54202 					t = duk_bd_decode(bd_ctx, 8);
54203 					curr_line = curr_line + t - 0x80;
54204 				}
54205 			} else {
54206 				/* 1 0 <2 bits> */
54207 				duk_uint_fast32_t t;
54208 				t = duk_bd_decode(bd_ctx, 2);
54209 				curr_line = curr_line + t + 1;
54210 			}
54211 		} else {
54212 			/* 0: no change */
54213 		}
54214 
54215 		n--;
54216 	}
54217 
54218 	DUK_DDD(DUK_DDDPRINT("pc2line lookup result: pc %ld -> line %ld", (long) pc, (long) curr_line));
54219 	return curr_line;
54220 
54221  pc2line_error:
54222 	DUK_D(DUK_DPRINT("pc2line conversion failed for pc=%ld", (long) pc));
54223 	return 0;
54224 }
54225 
54226 DUK_INTERNAL duk_uint_fast32_t duk_hobject_pc2line_query(duk_hthread *thr, duk_idx_t idx_func, duk_uint_fast32_t pc) {
54227 	duk_hbuffer_fixed *pc2line;
54228 	duk_uint_fast32_t line;
54229 
54230 	/* XXX: now that pc2line is used by the debugger quite heavily in
54231 	 * checked execution, this should be optimized to avoid value stack
54232 	 * and perhaps also implement some form of pc2line caching (see
54233 	 * future work in debugger.rst).
54234 	 */
54235 
54236 	duk_get_prop_stridx(thr, idx_func, DUK_STRIDX_INT_PC2LINE);
54237 	pc2line = (duk_hbuffer_fixed *) (void *) duk_get_hbuffer(thr, -1);
54238 	if (pc2line != NULL) {
54239 		DUK_ASSERT(!DUK_HBUFFER_HAS_DYNAMIC((duk_hbuffer *) pc2line) && !DUK_HBUFFER_HAS_EXTERNAL((duk_hbuffer *) pc2line));
54240 		line = duk__hobject_pc2line_query_raw(thr, pc2line, (duk_uint_fast32_t) pc);
54241 	} else {
54242 		line = 0;
54243 	}
54244 	duk_pop(thr);
54245 
54246 	return line;
54247 }
54248 
54249 #endif  /* DUK_USE_PC2LINE */
54250 #line 1 "duk_hobject_props.c"
54251 /*
54252  *  duk_hobject property access functionality.
54253  *
54254  *  This is very central functionality for size, performance, and compliance.
54255  *  It is also rather intricate; see hobject-algorithms.rst for discussion on
54256  *  the algorithms and memory-management.rst for discussion on refcounts and
54257  *  side effect issues.
54258  *
54259  *  Notes:
54260  *
54261  *    - It might be tempting to assert "refcount nonzero" for objects
54262  *      being operated on, but that's not always correct: objects with
54263  *      a zero refcount may be operated on by the refcount implementation
54264  *      (finalization) for instance.  Hence, no refcount assertions are made.
54265  *
54266  *    - Many operations (memory allocation, identifier operations, etc)
54267  *      may cause arbitrary side effects (e.g. through GC and finalization).
54268  *      These side effects may invalidate duk_tval pointers which point to
54269  *      areas subject to reallocation (like value stack).  Heap objects
54270  *      themselves have stable pointers.  Holding heap object pointers or
54271  *      duk_tval copies is not problematic with respect to side effects;
54272  *      care must be taken when holding and using argument duk_tval pointers.
54273  *
54274  *    - If a finalizer is executed, it may operate on the the same object
54275  *      we're currently dealing with.  For instance, the finalizer might
54276  *      delete a certain property which has already been looked up and
54277  *      confirmed to exist.  Ideally finalizers would be disabled if GC
54278  *      happens during property access.  At the moment property table realloc
54279  *      disables finalizers, and all DECREFs may cause arbitrary changes so
54280  *      handle DECREF carefully.
54281  *
54282  *    - The order of operations for a DECREF matters.  When DECREF is executed,
54283  *      the entire object graph must be consistent; note that a refzero may
54284  *      lead to a mark-and-sweep through a refcount finalizer.  Use NORZ macros
54285  *      and an explicit DUK_REFZERO_CHECK_xxx() if achieving correct order is hard.
54286  */
54287 
54288 /*
54289  *  XXX: array indices are mostly typed as duk_uint32_t here; duk_uarridx_t
54290  *  might be more appropriate.
54291  */
54292 
54293 /* #include duk_internal.h -> already included */
54294 
54295 /*
54296  *  Local defines
54297  */
54298 
54299 #define DUK__NO_ARRAY_INDEX             DUK_HSTRING_NO_ARRAY_INDEX
54300 
54301 /* Marker values for hash part. */
54302 #define DUK__HASH_UNUSED                DUK_HOBJECT_HASHIDX_UNUSED
54303 #define DUK__HASH_DELETED               DUK_HOBJECT_HASHIDX_DELETED
54304 
54305 /* Valstack space that suffices for all local calls, excluding any recursion
54306  * into ECMAScript or Duktape/C calls (Proxy, getters, etc).
54307  */
54308 #define DUK__VALSTACK_SPACE             10
54309 
54310 /* Valstack space allocated especially for proxy lookup which does a
54311  * recursive property lookup.
54312  */
54313 #define DUK__VALSTACK_PROXY_LOOKUP      20
54314 
54315 /*
54316  *  Local prototypes
54317  */
54318 
54319 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);
54320 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);
54321 DUK_LOCAL_DECL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc);
54322 
54323 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);
54324 DUK_LOCAL_DECL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj);
54325 
54326 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);
54327 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);
54328 
54329 /*
54330  *  Misc helpers
54331  */
54332 
54333 /* Convert a duk_tval number (caller checks) to a 32-bit index.  Returns
54334  * DUK__NO_ARRAY_INDEX if the number is not whole or not a valid array
54335  * index.
54336  */
54337 /* XXX: for fastints, could use a variant which assumes a double duk_tval
54338  * (and doesn't need to check for fastint again).
54339  */
54340 DUK_LOCAL duk_uint32_t duk__tval_number_to_arr_idx(duk_tval *tv) {
54341 	duk_double_t dbl;
54342 	duk_uint32_t idx;
54343 
54344 	DUK_ASSERT(tv != NULL);
54345 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
54346 
54347 	/* -0 is accepted here as index 0 because ToString(-0) == "0" which is
54348 	 * in canonical form and thus an array index.
54349 	 */
54350 	dbl = DUK_TVAL_GET_NUMBER(tv);
54351 	idx = (duk_uint32_t) dbl;
54352 	if ((duk_double_t) idx == dbl) {
54353 	        /* Is whole and within 32 bit range.  If the value happens to be 0xFFFFFFFF,
54354 		 * it's not a valid array index but will then match DUK__NO_ARRAY_INDEX.
54355 		 */
54356 		return idx;
54357 	}
54358 	return DUK__NO_ARRAY_INDEX;
54359 }
54360 
54361 #if defined(DUK_USE_FASTINT)
54362 /* Convert a duk_tval fastint (caller checks) to a 32-bit index. */
54363 DUK_LOCAL duk_uint32_t duk__tval_fastint_to_arr_idx(duk_tval *tv) {
54364 	duk_int64_t t;
54365 
54366 	DUK_ASSERT(tv != NULL);
54367 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
54368 
54369 	t = DUK_TVAL_GET_FASTINT(tv);
54370 	if (((duk_uint64_t) t & ~DUK_U64_CONSTANT(0xffffffff)) != 0) {
54371 		/* Catches >0x100000000 and negative values. */
54372 		return DUK__NO_ARRAY_INDEX;
54373 	}
54374 
54375 	/* If the value happens to be 0xFFFFFFFF, it's not a valid array index
54376 	 * but will then match DUK__NO_ARRAY_INDEX.
54377 	 */
54378 	return (duk_uint32_t) t;
54379 }
54380 #endif  /* DUK_USE_FASTINT */
54381 
54382 /* Convert a duk_tval on the value stack (in a trusted index we don't validate)
54383  * to a string or symbol using ES2015 ToPropertyKey():
54384  * http://www.ecma-international.org/ecma-262/6.0/#sec-topropertykey.
54385  *
54386  * Also check if it's a valid array index and return that (or DUK__NO_ARRAY_INDEX
54387  * if not).
54388  */
54389 DUK_LOCAL duk_uint32_t duk__to_property_key(duk_hthread *thr, duk_idx_t idx, duk_hstring **out_h) {
54390 	duk_uint32_t arr_idx;
54391 	duk_hstring *h;
54392 	duk_tval *tv_dst;
54393 
54394 	DUK_ASSERT(thr != NULL);
54395 	DUK_ASSERT(out_h != NULL);
54396 	DUK_ASSERT(duk_is_valid_index(thr, idx));
54397 	DUK_ASSERT(idx < 0);
54398 
54399 	/* XXX: The revised ES2015 ToPropertyKey() handling (ES5.1 was just
54400 	 * ToString()) involves a ToPrimitive(), a symbol check, and finally
54401 	 * a ToString().  Figure out the best way to have a good fast path
54402 	 * but still be compliant and share code.
54403 	 */
54404 
54405 	tv_dst = DUK_GET_TVAL_NEGIDX(thr, idx);  /* intentionally unvalidated */
54406 	if (DUK_TVAL_IS_STRING(tv_dst)) {
54407 		/* Most important path: strings and plain symbols are used as
54408 		 * is.  For symbols the array index check below is unnecessary
54409 		 * (they're never valid array indices) but checking that the
54410 		 * string is a symbol would make the plain string path slower
54411 		 * unnecessarily.
54412 		 */
54413 		h = DUK_TVAL_GET_STRING(tv_dst);
54414 	} else {
54415 		h = duk_to_property_key_hstring(thr, idx);
54416 	}
54417 	DUK_ASSERT(h != NULL);
54418 	*out_h = h;
54419 
54420 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(h);
54421 	return arr_idx;
54422 }
54423 
54424 DUK_LOCAL duk_uint32_t duk__push_tval_to_property_key(duk_hthread *thr, duk_tval *tv_key, duk_hstring **out_h) {
54425 	duk_push_tval(thr, tv_key);  /* XXX: could use an unsafe push here */
54426 	return duk__to_property_key(thr, -1, out_h);
54427 }
54428 
54429 /* String is an own (virtual) property of a plain buffer. */
54430 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) {
54431 	DUK_UNREF(thr);
54432 
54433 	/* Virtual index properties.  Checking explicitly for
54434 	 * 'arr_idx != DUK__NO_ARRAY_INDEX' is not necessary
54435 	 * because DUK__NO_ARRAY_INDEXi is always larger than
54436 	 * maximum allowed buffer size.
54437 	 */
54438 	DUK_ASSERT(DUK__NO_ARRAY_INDEX >= DUK_HBUFFER_GET_SIZE(buf));
54439 	if (arr_idx < DUK_HBUFFER_GET_SIZE(buf)) {
54440 		return 1;
54441 	}
54442 
54443 	/* Other virtual properties. */
54444 	return (key == DUK_HTHREAD_STRING_LENGTH(thr));
54445 }
54446 
54447 /*
54448  *  Helpers for managing property storage size
54449  */
54450 
54451 /* Get default hash part size for a certain entry part size. */
54452 #if defined(DUK_USE_HOBJECT_HASH_PART)
54453 DUK_LOCAL duk_uint32_t duk__get_default_h_size(duk_uint32_t e_size) {
54454 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
54455 
54456 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
54457 		duk_uint32_t res;
54458 		duk_uint32_t tmp;
54459 
54460 		/* Hash size should be 2^N where N is chosen so that 2^N is
54461 		 * larger than e_size.  Extra shifting is used to ensure hash
54462 		 * is relatively sparse.
54463 		 */
54464 		tmp = e_size;
54465 		res = 2;  /* Result will be 2 ** (N + 1). */
54466 		while (tmp >= 0x40) {
54467 			tmp >>= 6;
54468 			res <<= 6;
54469 		}
54470 		while (tmp != 0) {
54471 			tmp >>= 1;
54472 			res <<= 1;
54473 		}
54474 		DUK_ASSERT((DUK_HOBJECT_MAX_PROPERTIES << 2U) > DUK_HOBJECT_MAX_PROPERTIES);  /* Won't wrap, even shifted by 2. */
54475 		DUK_ASSERT(res > e_size);
54476 		return res;
54477 	} else {
54478 		return 0;
54479 	}
54480 }
54481 #endif  /* USE_PROP_HASH_PART */
54482 
54483 /* Get minimum entry part growth for a certain size. */
54484 DUK_LOCAL duk_uint32_t duk__get_min_grow_e(duk_uint32_t e_size) {
54485 	duk_uint32_t res;
54486 
54487 	DUK_ASSERT(e_size <= DUK_HOBJECT_MAX_PROPERTIES);
54488 
54489 	res = (e_size + DUK_USE_HOBJECT_ENTRY_MINGROW_ADD) / DUK_USE_HOBJECT_ENTRY_MINGROW_DIVISOR;
54490 	DUK_ASSERT(res >= 1);  /* important for callers */
54491 	return res;
54492 }
54493 
54494 /* Get minimum array part growth for a certain size. */
54495 DUK_LOCAL duk_uint32_t duk__get_min_grow_a(duk_uint32_t a_size) {
54496 	duk_uint32_t res;
54497 
54498 	DUK_ASSERT((duk_size_t) a_size <= DUK_HOBJECT_MAX_PROPERTIES);
54499 
54500 	res = (a_size + DUK_USE_HOBJECT_ARRAY_MINGROW_ADD) / DUK_USE_HOBJECT_ARRAY_MINGROW_DIVISOR;
54501 	DUK_ASSERT(res >= 1);  /* important for callers */
54502 	return res;
54503 }
54504 
54505 /* Count actually used entry part entries (non-NULL keys). */
54506 DUK_LOCAL duk_uint32_t duk__count_used_e_keys(duk_hthread *thr, duk_hobject *obj) {
54507 	duk_uint_fast32_t i;
54508 	duk_uint_fast32_t n = 0;
54509 	duk_hstring **e;
54510 
54511 	DUK_ASSERT(obj != NULL);
54512 	DUK_UNREF(thr);
54513 
54514 	e = DUK_HOBJECT_E_GET_KEY_BASE(thr->heap, obj);
54515 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
54516 		if (*e++) {
54517 			n++;
54518 		}
54519 	}
54520 	return (duk_uint32_t) n;
54521 }
54522 
54523 /* Count actually used array part entries and array minimum size.
54524  * NOTE: 'out_min_size' can be computed much faster by starting from the
54525  * end and breaking out early when finding first used entry, but this is
54526  * not needed now.
54527  */
54528 DUK_LOCAL void duk__compute_a_stats(duk_hthread *thr, duk_hobject *obj, duk_uint32_t *out_used, duk_uint32_t *out_min_size) {
54529 	duk_uint_fast32_t i;
54530 	duk_uint_fast32_t used = 0;
54531 	duk_uint_fast32_t highest_idx = (duk_uint_fast32_t) -1;  /* see below */
54532 	duk_tval *a;
54533 
54534 	DUK_ASSERT(obj != NULL);
54535 	DUK_ASSERT(out_used != NULL);
54536 	DUK_ASSERT(out_min_size != NULL);
54537 	DUK_UNREF(thr);
54538 
54539 	a = DUK_HOBJECT_A_GET_BASE(thr->heap, obj);
54540 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
54541 		duk_tval *tv = a++;
54542 		if (!DUK_TVAL_IS_UNUSED(tv)) {
54543 			used++;
54544 			highest_idx = i;
54545 		}
54546 	}
54547 
54548 	/* Initial value for highest_idx is -1 coerced to unsigned.  This
54549 	 * is a bit odd, but (highest_idx + 1) will then wrap to 0 below
54550 	 * for out_min_size as intended.
54551 	 */
54552 
54553 	*out_used = (duk_uint32_t) used;
54554 	*out_min_size = (duk_uint32_t) (highest_idx + 1);  /* 0 if no used entries */
54555 }
54556 
54557 /* Check array density and indicate whether or not the array part should be abandoned. */
54558 DUK_LOCAL duk_bool_t duk__abandon_array_density_check(duk_uint32_t a_used, duk_uint32_t a_size) {
54559 	/*
54560 	 *  Array abandon check; abandon if:
54561 	 *
54562 	 *    new_used / new_size < limit
54563 	 *    new_used < limit * new_size        || limit is 3 bits fixed point
54564 	 *    new_used < limit' / 8 * new_size   || *8
54565 	 *    8*new_used < limit' * new_size     || :8
54566 	 *    new_used < limit' * (new_size / 8)
54567 	 *
54568 	 *  Here, new_used = a_used, new_size = a_size.
54569 	 *
54570 	 *  Note: some callers use approximate values for a_used and/or a_size
54571 	 *  (e.g. dropping a '+1' term).  This doesn't affect the usefulness
54572 	 *  of the check, but may confuse debugging.
54573 	 */
54574 
54575 	return (a_used < DUK_USE_HOBJECT_ARRAY_ABANDON_LIMIT * (a_size >> 3));
54576 }
54577 
54578 /* Fast check for extending array: check whether or not a slow density check is required. */
54579 DUK_LOCAL duk_bool_t duk__abandon_array_slow_check_required(duk_uint32_t arr_idx, duk_uint32_t old_size) {
54580 	/*
54581 	 *  In a fast check we assume old_size equals old_used (i.e., existing
54582 	 *  array is fully dense).
54583 	 *
54584 	 *  Slow check if:
54585 	 *
54586 	 *    (new_size - old_size) / old_size > limit
54587 	 *    new_size - old_size > limit * old_size
54588 	 *    new_size > (1 + limit) * old_size        || limit' is 3 bits fixed point
54589 	 *    new_size > (1 + (limit' / 8)) * old_size || * 8
54590 	 *    8 * new_size > (8 + limit') * old_size   || : 8
54591 	 *    new_size > (8 + limit') * (old_size / 8)
54592 	 *    new_size > limit'' * (old_size / 8)      || limit'' = 9 -> max 25% increase
54593 	 *    arr_idx + 1 > limit'' * (old_size / 8)
54594 	 *
54595 	 *  This check doesn't work well for small values, so old_size is rounded
54596 	 *  up for the check (and the '+ 1' of arr_idx can be ignored in practice):
54597 	 *
54598 	 *    arr_idx > limit'' * ((old_size + 7) / 8)
54599 	 */
54600 
54601 	return (arr_idx > DUK_USE_HOBJECT_ARRAY_FAST_RESIZE_LIMIT * ((old_size + 7) >> 3));
54602 }
54603 
54604 /*
54605  *  Proxy helpers
54606  */
54607 
54608 #if defined(DUK_USE_ES6_PROXY)
54609 DUK_INTERNAL duk_bool_t duk_hobject_proxy_check(duk_hobject *obj, duk_hobject **out_target, duk_hobject **out_handler) {
54610 	duk_hproxy *h_proxy;
54611 
54612 	DUK_ASSERT(obj != NULL);
54613 	DUK_ASSERT(out_target != NULL);
54614 	DUK_ASSERT(out_handler != NULL);
54615 
54616 	/* Caller doesn't need to check exotic proxy behavior (but does so for
54617 	 * some fast paths).
54618 	 */
54619 	if (DUK_LIKELY(!DUK_HOBJECT_IS_PROXY(obj))) {
54620 		return 0;
54621 	}
54622 	h_proxy = (duk_hproxy *) obj;
54623 	DUK_ASSERT_HPROXY_VALID(h_proxy);
54624 
54625 	DUK_ASSERT(h_proxy->handler != NULL);
54626 	DUK_ASSERT(h_proxy->target != NULL);
54627 	*out_handler = h_proxy->handler;
54628 	*out_target = h_proxy->target;
54629 
54630 	return 1;
54631 }
54632 #endif  /* DUK_USE_ES6_PROXY */
54633 
54634 /* Get Proxy target object.  If the argument is not a Proxy, return it as is.
54635  * If a Proxy is revoked, an error is thrown.
54636  */
54637 #if defined(DUK_USE_ES6_PROXY)
54638 DUK_INTERNAL duk_hobject *duk_hobject_resolve_proxy_target(duk_hobject *obj) {
54639 	DUK_ASSERT(obj != NULL);
54640 
54641 	/* Resolve Proxy targets until Proxy chain ends.  No explicit check for
54642 	 * a Proxy loop: user code cannot create such a loop (it would only be
54643 	 * possible by editing duk_hproxy references directly).
54644 	 */
54645 
54646 	while (DUK_HOBJECT_IS_PROXY(obj)) {
54647 		duk_hproxy *h_proxy;
54648 
54649 		h_proxy = (duk_hproxy *) obj;
54650 		DUK_ASSERT_HPROXY_VALID(h_proxy);
54651 		obj = h_proxy->target;
54652 		DUK_ASSERT(obj != NULL);
54653 	}
54654 
54655 	DUK_ASSERT(obj != NULL);
54656 	return obj;
54657 }
54658 #endif  /* DUK_USE_ES6_PROXY */
54659 
54660 #if defined(DUK_USE_ES6_PROXY)
54661 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) {
54662 	duk_hobject *h_handler;
54663 
54664 	DUK_ASSERT(thr != NULL);
54665 	DUK_ASSERT(obj != NULL);
54666 	DUK_ASSERT(tv_key != NULL);
54667 	DUK_ASSERT(out_target != NULL);
54668 
54669 	if (!duk_hobject_proxy_check(obj, out_target, &h_handler)) {
54670 		return 0;
54671 	}
54672 	DUK_ASSERT(*out_target != NULL);
54673 	DUK_ASSERT(h_handler != NULL);
54674 
54675 	/* XXX: At the moment Duktape accesses internal keys like _Finalizer using a
54676 	 * normal property set/get which would allow a proxy handler to interfere with
54677 	 * such behavior and to get access to internal key strings.  This is not a problem
54678 	 * as such because internal key strings can be created in other ways too (e.g.
54679 	 * through buffers).  The best fix is to change Duktape internal lookups to
54680 	 * skip proxy behavior.  Until that, internal property accesses bypass the
54681 	 * proxy and are applied to the target (as if the handler did not exist).
54682 	 * This has some side effects, see test-bi-proxy-internal-keys.js.
54683 	 */
54684 
54685 	if (DUK_TVAL_IS_STRING(tv_key)) {
54686 		duk_hstring *h_key = (duk_hstring *) DUK_TVAL_GET_STRING(tv_key);
54687 		DUK_ASSERT(h_key != NULL);
54688 		if (DUK_HSTRING_HAS_HIDDEN(h_key)) {
54689 			/* Symbol accesses must go through proxy lookup in ES2015.
54690 			 * Hidden symbols behave like Duktape 1.x internal keys
54691 			 * and currently won't.
54692 			 */
54693 			DUK_DDD(DUK_DDDPRINT("hidden key, skip proxy handler and apply to target"));
54694 			return 0;
54695 		}
54696 	}
54697 
54698 	/* The handler is looked up with a normal property lookup; it may be an
54699 	 * accessor or the handler object itself may be a proxy object.  If the
54700 	 * handler is a proxy, we need to extend the valstack as we make a
54701 	 * recursive proxy check without a function call in between (in fact
54702 	 * there is no limit to the potential recursion here).
54703 	 *
54704 	 * (For sanity, proxy creation rejects another proxy object as either
54705 	 * the handler or the target at the moment so recursive proxy cases
54706 	 * are not realized now.)
54707 	 */
54708 
54709 	/* XXX: C recursion limit if proxies are allowed as handler/target values */
54710 
54711 	duk_require_stack(thr, DUK__VALSTACK_PROXY_LOOKUP);
54712 	duk_push_hobject(thr, h_handler);
54713 	if (duk_get_prop_stridx_short(thr, -1, stridx_trap)) {
54714 		/* -> [ ... handler trap ] */
54715 		duk_insert(thr, -2);  /* -> [ ... trap handler ] */
54716 
54717 		/* stack prepped for func call: [ ... trap handler ] */
54718 		return 1;
54719 	} else {
54720 		duk_pop_2_unsafe(thr);
54721 		return 0;
54722 	}
54723 }
54724 #endif  /* DUK_USE_ES6_PROXY */
54725 
54726 /*
54727  *  Reallocate property allocation, moving properties to the new allocation.
54728  *
54729  *  Includes key compaction, rehashing, and can also optionally abandon
54730  *  the array part, 'migrating' array entries into the beginning of the
54731  *  new entry part.
54732  *
54733  *  There is no support for in-place reallocation or just compacting keys
54734  *  without resizing the property allocation.  This is intentional to keep
54735  *  code size minimal, but would be useful future work.
54736  *
54737  *  The implementation is relatively straightforward, except for the array
54738  *  abandonment process.  Array abandonment requires that new string keys
54739  *  are interned, which may trigger GC.  All keys interned so far must be
54740  *  reachable for GC at all times and correctly refcounted for; valstack is
54741  *  used for that now.
54742  *
54743  *  Also, a GC triggered during this reallocation process must not interfere
54744  *  with the object being resized.  This is currently controlled by preventing
54745  *  finalizers (as they may affect ANY object) and object compaction in
54746  *  mark-and-sweep.  It would suffice to protect only this particular object
54747  *  from compaction, however.  DECREF refzero cascades are side effect free
54748  *  and OK.
54749  *
54750  *  Note: because we need to potentially resize the valstack (as part
54751  *  of abandoning the array part), any tval pointers to the valstack
54752  *  will become invalid after this call.
54753  */
54754 
54755 DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
54756                                             duk_hobject *obj,
54757                                             duk_uint32_t new_e_size,
54758                                             duk_uint32_t new_a_size,
54759                                             duk_uint32_t new_h_size,
54760                                             duk_bool_t abandon_array) {
54761 	duk_small_uint_t prev_ms_base_flags;
54762 	duk_uint32_t new_alloc_size;
54763 	duk_uint32_t new_e_size_adjusted;
54764 	duk_uint8_t *new_p;
54765 	duk_hstring **new_e_k;
54766 	duk_propvalue *new_e_pv;
54767 	duk_uint8_t *new_e_f;
54768 	duk_tval *new_a;
54769 	duk_uint32_t *new_h;
54770 	duk_uint32_t new_e_next;
54771 	duk_uint_fast32_t i;
54772 	duk_size_t array_copy_size;
54773 #if defined(DUK_USE_ASSERTIONS)
54774 	duk_bool_t prev_error_not_allowed;
54775 #endif
54776 
54777 	DUK_ASSERT(thr != NULL);
54778 	DUK_ASSERT(obj != NULL);
54779 	DUK_ASSERT(!abandon_array || new_a_size == 0);  /* if abandon_array, new_a_size must be 0 */
54780 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || (DUK_HOBJECT_GET_ESIZE(obj) == 0 && DUK_HOBJECT_GET_ASIZE(obj) == 0));
54781 	DUK_ASSERT(new_h_size == 0 || new_h_size >= new_e_size);  /* required to guarantee success of rehashing,
54782 	                                                           * intentionally use unadjusted new_e_size
54783 	                                                           */
54784 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
54785 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
54786 
54787 	DUK_STATS_INC(thr->heap, stats_object_realloc_props);
54788 
54789 	/*
54790 	 *  Pre resize assertions.
54791 	 */
54792 
54793 #if defined(DUK_USE_ASSERTIONS)
54794 	/* XXX: pre-checks (such as no duplicate keys) */
54795 #endif
54796 
54797 	/*
54798 	 *  For property layout 1, tweak e_size to ensure that the whole entry
54799 	 *  part (key + val + flags) is a suitable multiple for alignment
54800 	 *  (platform specific).
54801 	 *
54802 	 *  Property layout 2 does not require this tweaking and is preferred
54803 	 *  on low RAM platforms requiring alignment.
54804 	 */
54805 
54806 #if defined(DUK_USE_HOBJECT_LAYOUT_2) || defined(DUK_USE_HOBJECT_LAYOUT_3)
54807 	DUK_DDD(DUK_DDDPRINT("using layout 2 or 3, no need to pad e_size: %ld", (long) new_e_size));
54808 	new_e_size_adjusted = new_e_size;
54809 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && (DUK_HOBJECT_ALIGN_TARGET == 1)
54810 	DUK_DDD(DUK_DDDPRINT("using layout 1, but no need to pad e_size: %ld", (long) new_e_size));
54811 	new_e_size_adjusted = new_e_size;
54812 #elif defined(DUK_USE_HOBJECT_LAYOUT_1) && ((DUK_HOBJECT_ALIGN_TARGET == 4) || (DUK_HOBJECT_ALIGN_TARGET == 8))
54813 	new_e_size_adjusted = (new_e_size + (duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U) &
54814 	                      (~((duk_uint32_t) DUK_HOBJECT_ALIGN_TARGET - 1U));
54815 	DUK_DDD(DUK_DDDPRINT("using layout 1, and alignment target is %ld, adjusted e_size: %ld -> %ld",
54816 	                     (long) DUK_HOBJECT_ALIGN_TARGET, (long) new_e_size, (long) new_e_size_adjusted));
54817 	DUK_ASSERT(new_e_size_adjusted >= new_e_size);
54818 #else
54819 #error invalid hobject layout defines
54820 #endif
54821 
54822 	/*
54823 	 *  Debug logging after adjustment.
54824 	 */
54825 
54826 	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 "
54827 	                     "{e_size=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
54828 	                     (void *) obj,
54829 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
54830 	                                                       DUK_HOBJECT_GET_ASIZE(obj),
54831 	                                                       DUK_HOBJECT_GET_HSIZE(obj)),
54832 	                     (long) DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size),
54833 	                     (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
54834 	                     (long) DUK_HOBJECT_GET_ESIZE(obj),
54835 	                     (long) DUK_HOBJECT_GET_ENEXT(obj),
54836 	                     (long) DUK_HOBJECT_GET_ASIZE(obj),
54837 	                     (long) DUK_HOBJECT_GET_HSIZE(obj),
54838 	                     (long) new_e_size_adjusted,
54839 	                     (long) new_a_size,
54840 	                     (long) new_h_size,
54841 	                     (long) abandon_array,
54842 	                     (long) new_e_size));
54843 
54844 	/*
54845 	 *  Property count check.  This is the only point where we ensure that
54846 	 *  we don't get more (allocated) property space that we can handle.
54847 	 *  There aren't hard limits as such, but some algorithms may fail
54848 	 *  if we get too close to the 4G property limit.
54849 	 *
54850 	 *  Since this works based on allocation size (not actually used size),
54851 	 *  the limit is a bit approximate but good enough in practice.
54852 	 */
54853 
54854 	if (new_e_size_adjusted + new_a_size > DUK_HOBJECT_MAX_PROPERTIES) {
54855 		DUK_ERROR_ALLOC_FAILED(thr);
54856 		DUK_WO_NORETURN(return;);
54857 	}
54858 
54859 	/*
54860 	 *  Compute new alloc size and alloc new area.
54861 	 *
54862 	 *  The new area is not tracked in the heap at all, so it's critical
54863 	 *  we get to free/keep it in a controlled manner.
54864 	 */
54865 
54866 #if defined(DUK_USE_ASSERTIONS)
54867 	/* Whole path must be error throw free, but we may be called from
54868 	 * within error handling so can't assert for error_not_allowed == 0.
54869 	 */
54870 	prev_error_not_allowed = thr->heap->error_not_allowed;
54871 	thr->heap->error_not_allowed = 1;
54872 #endif
54873 	prev_ms_base_flags = thr->heap->ms_base_flags;
54874 	thr->heap->ms_base_flags |=
54875 	        DUK_MS_FLAG_NO_OBJECT_COMPACTION;      /* Avoid attempt to compact the current object (all objects really). */
54876 	thr->heap->pf_prevent_count++;                 /* Avoid finalizers. */
54877 	DUK_ASSERT(thr->heap->pf_prevent_count != 0);  /* Wrap. */
54878 
54879 	new_alloc_size = DUK_HOBJECT_P_COMPUTE_SIZE(new_e_size_adjusted, new_a_size, new_h_size);
54880 	DUK_DDD(DUK_DDDPRINT("new hobject allocation size is %ld", (long) new_alloc_size));
54881 	if (new_alloc_size == 0) {
54882 		DUK_ASSERT(new_e_size_adjusted == 0);
54883 		DUK_ASSERT(new_a_size == 0);
54884 		DUK_ASSERT(new_h_size == 0);
54885 		new_p = NULL;
54886 	} else {
54887 		/* Alloc may trigger mark-and-sweep but no compaction, and
54888 		 * cannot throw.
54889 		 */
54890 #if 0  /* XXX: inject test */
54891 		if (1) {
54892 			new_p = NULL;
54893 			goto alloc_failed;
54894 		}
54895 #endif
54896 		new_p = (duk_uint8_t *) DUK_ALLOC(thr->heap, new_alloc_size);
54897 		if (new_p == NULL) {
54898 			/* NULL always indicates alloc failure because
54899 			 * new_alloc_size > 0.
54900 			 */
54901 			goto alloc_failed;
54902 		}
54903 	}
54904 
54905 	/* Set up pointers to the new property area: this is hidden behind a macro
54906 	 * because it is memory layout specific.
54907 	 */
54908 	DUK_HOBJECT_P_SET_REALLOC_PTRS(new_p, new_e_k, new_e_pv, new_e_f, new_a, new_h,
54909 	                               new_e_size_adjusted, new_a_size, new_h_size);
54910 	DUK_UNREF(new_h);  /* happens when hash part dropped */
54911 	new_e_next = 0;
54912 
54913 	/* if new_p == NULL, all of these pointers are NULL */
54914 	DUK_ASSERT((new_p != NULL) ||
54915 	           (new_e_k == NULL && new_e_pv == NULL && new_e_f == NULL &&
54916 	            new_a == NULL && new_h == NULL));
54917 
54918 	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",
54919 	                     (long) new_alloc_size, (void *) new_e_k, (void *) new_e_pv, (void *) new_e_f,
54920 	                     (void *) new_a, (void *) new_h));
54921 
54922 	/*
54923 	 *  Migrate array part to start of entries if requested.
54924 	 *
54925 	 *  Note: from an enumeration perspective the order of entry keys matters.
54926 	 *  Array keys should appear wherever they appeared before the array abandon
54927 	 *  operation.  (This no longer matters much because keys are ES2015 sorted.)
54928 	 */
54929 
54930 	if (abandon_array) {
54931 		/* Assuming new_a_size == 0, and that entry part contains
54932 		 * no conflicting keys, refcounts do not need to be adjusted for
54933 		 * the values, as they remain exactly the same.
54934 		 *
54935 		 * The keys, however, need to be interned, incref'd, and be
54936 		 * reachable for GC.  Any intern attempt may trigger a GC and
54937 		 * claim any non-reachable strings, so every key must be reachable
54938 		 * at all times.  Refcounts must be correct to satisfy refcount
54939 		 * assertions.
54940 		 *
54941 		 * A longjmp must not occur here, as the new_p allocation would
54942 		 * leak.  Refcounts would come out correctly as the interned
54943 		 * strings are valstack tracked.
54944 		 */
54945 		DUK_ASSERT(new_a_size == 0);
54946 
54947 		DUK_STATS_INC(thr->heap, stats_object_abandon_array);
54948 
54949 		for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
54950 			duk_tval *tv1;
54951 			duk_tval *tv2;
54952 			duk_hstring *key;
54953 
54954 			DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
54955 
54956 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
54957 			if (DUK_TVAL_IS_UNUSED(tv1)) {
54958 				continue;
54959 			}
54960 
54961 			DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
54962 			           new_e_pv != NULL && new_e_f != NULL);
54963 
54964 			/*
54965 			 *  Intern key via the valstack to ensure reachability behaves
54966 			 *  properly.  We must avoid longjmp's here so use non-checked
54967 			 *  primitives.
54968 			 *
54969 			 *  Note: duk_check_stack() potentially reallocs the valstack,
54970 			 *  invalidating any duk_tval pointers to valstack.  Callers
54971 			 *  must be careful.
54972 			 */
54973 
54974 #if 0  /* XXX: inject test */
54975 			if (1) {
54976 				goto abandon_error;
54977 			}
54978 #endif
54979 			/* Never shrinks; auto-adds DUK_VALSTACK_INTERNAL_EXTRA, which
54980 			 * is generous.
54981 			 */
54982 			if (!duk_check_stack(thr, 1)) {
54983 				goto abandon_error;
54984 			}
54985 			DUK_ASSERT_VALSTACK_SPACE(thr, 1);
54986 			key = duk_heap_strtable_intern_u32(thr->heap, (duk_uint32_t) i);
54987 			if (key == NULL) {
54988 				goto abandon_error;
54989 			}
54990 			duk_push_hstring(thr, key);  /* keep key reachable for GC etc; guaranteed not to fail */
54991 
54992 			/* Key is now reachable in the valstack, don't INCREF
54993 			 * the new allocation yet (we'll steal the refcounts
54994 			 * from the value stack once all keys are done).
54995 			 */
54996 
54997 			new_e_k[new_e_next] = key;
54998 			tv2 = &new_e_pv[new_e_next].v;  /* array entries are all plain values */
54999 			DUK_TVAL_SET_TVAL(tv2, tv1);
55000 			new_e_f[new_e_next] = DUK_PROPDESC_FLAG_WRITABLE |
55001 			                      DUK_PROPDESC_FLAG_ENUMERABLE |
55002 			                      DUK_PROPDESC_FLAG_CONFIGURABLE;
55003 			new_e_next++;
55004 
55005 			/* Note: new_e_next matches pushed temp key count, and nothing can
55006 			 * fail above between the push and this point.
55007 			 */
55008 		}
55009 
55010 		/* Steal refcounts from value stack. */
55011 		DUK_DDD(DUK_DDDPRINT("abandon array: pop %ld key temps from valstack", (long) new_e_next));
55012 		duk_pop_n_nodecref_unsafe(thr, (duk_idx_t) new_e_next);
55013 	}
55014 
55015 	/*
55016 	 *  Copy keys and values in the entry part (compacting them at the same time).
55017 	 */
55018 
55019 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55020 		duk_hstring *key;
55021 
55022 		DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL);
55023 
55024 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
55025 		if (key == NULL) {
55026 			continue;
55027 		}
55028 
55029 		DUK_ASSERT(new_p != NULL && new_e_k != NULL &&
55030 		           new_e_pv != NULL && new_e_f != NULL);
55031 
55032 		new_e_k[new_e_next] = key;
55033 		new_e_pv[new_e_next] = DUK_HOBJECT_E_GET_VALUE(thr->heap, obj, i);
55034 		new_e_f[new_e_next] = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
55035 		new_e_next++;
55036 	}
55037 	/* the entries [new_e_next, new_e_size_adjusted[ are left uninitialized on purpose (ok, not gc reachable) */
55038 
55039 	/*
55040 	 *  Copy array elements to new array part.  If the new array part is
55041 	 *  larger, initialize the unused entries as UNUSED because they are
55042 	 *  GC reachable.
55043 	 */
55044 
55045 #if defined(DUK_USE_ASSERTIONS)
55046 	/* Caller must have decref'd values above new_a_size (if that is necessary). */
55047 	if (!abandon_array) {
55048 		for (i = new_a_size; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
55049 			duk_tval *tv;
55050 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
55051 			DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
55052 		}
55053 	}
55054 #endif
55055 	if (new_a_size > DUK_HOBJECT_GET_ASIZE(obj)) {
55056 		array_copy_size = sizeof(duk_tval) * DUK_HOBJECT_GET_ASIZE(obj);
55057 	} else {
55058 		array_copy_size = sizeof(duk_tval) * new_a_size;
55059 	}
55060 
55061 	DUK_ASSERT(new_a != NULL || array_copy_size == 0U);
55062 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, obj) != NULL || array_copy_size == 0U);
55063 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) > 0 || array_copy_size == 0U);
55064 	duk_memcpy_unsafe((void *) new_a,
55065 	                  (const void *) DUK_HOBJECT_A_GET_BASE(thr->heap, obj),
55066 	                  array_copy_size);
55067 
55068 	for (i = DUK_HOBJECT_GET_ASIZE(obj); i < new_a_size; i++) {
55069 		duk_tval *tv = &new_a[i];
55070 		DUK_TVAL_SET_UNUSED(tv);
55071 	}
55072 
55073 	/*
55074 	 *  Rebuild the hash part always from scratch (guaranteed to finish
55075 	 *  as long as caller gave consistent parameters).
55076 	 *
55077 	 *  Any resize of hash part requires rehashing.  In addition, by rehashing
55078 	 *  get rid of any elements marked deleted (DUK__HASH_DELETED) which is critical
55079 	 *  to ensuring the hash part never fills up.
55080 	 */
55081 
55082 #if defined(DUK_USE_HOBJECT_HASH_PART)
55083 	if (new_h_size == 0) {
55084 		DUK_DDD(DUK_DDDPRINT("no hash part, no rehash"));
55085 	} else {
55086 		duk_uint32_t mask;
55087 
55088 		DUK_ASSERT(new_h != NULL);
55089 
55090 		/* fill new_h with u32 0xff = UNUSED */
55091 		DUK_ASSERT(new_h_size > 0);
55092 		duk_memset(new_h, 0xff, sizeof(duk_uint32_t) * new_h_size);
55093 
55094 		DUK_ASSERT(new_e_next <= new_h_size);  /* equality not actually possible */
55095 
55096 		mask = new_h_size - 1;
55097 		for (i = 0; i < new_e_next; i++) {
55098 			duk_hstring *key = new_e_k[i];
55099 			duk_uint32_t j, step;
55100 
55101 			DUK_ASSERT(key != NULL);
55102 			j = DUK_HSTRING_GET_HASH(key) & mask;
55103 			step = 1;  /* Cache friendly but clustering prone. */
55104 
55105 			for (;;) {
55106 				DUK_ASSERT(new_h[j] != DUK__HASH_DELETED);  /* should never happen */
55107 				if (new_h[j] == DUK__HASH_UNUSED) {
55108 					DUK_DDD(DUK_DDDPRINT("rebuild hit %ld -> %ld", (long) j, (long) i));
55109 					new_h[j] = (duk_uint32_t) i;
55110 					break;
55111 				}
55112 				DUK_DDD(DUK_DDDPRINT("rebuild miss %ld, step %ld", (long) j, (long) step));
55113 				j = (j + step) & mask;
55114 
55115 				/* Guaranteed to finish (hash is larger than #props). */
55116 			}
55117 		}
55118 	}
55119 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55120 
55121 	/*
55122 	 *  Nice debug log.
55123 	 */
55124 
55125 	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 "
55126 	                   "{p=%p,e_size=%ld,e_next=%ld,a_size=%ld,h_size=%ld}, abandon_array=%ld, unadjusted new_e_size=%ld",
55127 	                   (void *) obj,
55128 	                   (long) DUK_HOBJECT_P_COMPUTE_SIZE(DUK_HOBJECT_GET_ESIZE(obj),
55129 	                                                     DUK_HOBJECT_GET_ASIZE(obj),
55130 	                                                     DUK_HOBJECT_GET_HSIZE(obj)),
55131 	                   (long) new_alloc_size,
55132 	                   (void *) DUK_HOBJECT_GET_PROPS(thr->heap, obj),
55133 	                   (long) DUK_HOBJECT_GET_ESIZE(obj),
55134 	                   (long) DUK_HOBJECT_GET_ENEXT(obj),
55135 	                   (long) DUK_HOBJECT_GET_ASIZE(obj),
55136 	                   (long) DUK_HOBJECT_GET_HSIZE(obj),
55137 	                   (void *) new_p,
55138 	                   (long) new_e_size_adjusted,
55139 	                   (long) new_e_next,
55140 	                   (long) new_a_size,
55141 	                   (long) new_h_size,
55142 	                   (long) abandon_array,
55143 	                   (long) new_e_size));
55144 
55145 	/*
55146 	 *  All done, switch properties ('p') allocation to new one.
55147 	 */
55148 
55149 	DUK_FREE_CHECKED(thr, DUK_HOBJECT_GET_PROPS(thr->heap, obj));  /* NULL obj->p is OK */
55150 	DUK_HOBJECT_SET_PROPS(thr->heap, obj, new_p);
55151 	DUK_HOBJECT_SET_ESIZE(obj, new_e_size_adjusted);
55152 	DUK_HOBJECT_SET_ENEXT(obj, new_e_next);
55153 	DUK_HOBJECT_SET_ASIZE(obj, new_a_size);
55154 	DUK_HOBJECT_SET_HSIZE(obj, new_h_size);
55155 
55156 	/* Clear array part flag only after switching. */
55157 	if (abandon_array) {
55158 		DUK_HOBJECT_CLEAR_ARRAY_PART(obj);
55159 	}
55160 
55161 	DUK_DDD(DUK_DDDPRINT("resize result: %!O", (duk_heaphdr *) obj));
55162 
55163 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
55164 	thr->heap->pf_prevent_count--;
55165 	thr->heap->ms_base_flags = prev_ms_base_flags;
55166 #if defined(DUK_USE_ASSERTIONS)
55167 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55168 	thr->heap->error_not_allowed = prev_error_not_allowed;
55169 #endif
55170 
55171 	/*
55172 	 *  Post resize assertions.
55173 	 */
55174 
55175 #if defined(DUK_USE_ASSERTIONS)
55176 	/* XXX: post-checks (such as no duplicate keys) */
55177 #endif
55178 	return;
55179 
55180 	/*
55181 	 *  Abandon array failed.  We don't need to DECREF anything
55182 	 *  because the references in the new allocation are not
55183 	 *  INCREF'd until abandon is complete.  The string interned
55184 	 *  keys are on the value stack and are handled normally by
55185 	 *  unwind.
55186 	 */
55187 
55188  abandon_error:
55189  alloc_failed:
55190 	DUK_D(DUK_DPRINT("object property table resize failed"));
55191 
55192 	DUK_FREE_CHECKED(thr, new_p);  /* OK for NULL. */
55193 
55194 	thr->heap->pf_prevent_count--;
55195 	thr->heap->ms_base_flags = prev_ms_base_flags;
55196 #if defined(DUK_USE_ASSERTIONS)
55197 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
55198 	thr->heap->error_not_allowed = prev_error_not_allowed;
55199 #endif
55200 
55201 	DUK_ERROR_ALLOC_FAILED(thr);
55202 	DUK_WO_NORETURN(return;);
55203 }
55204 
55205 /*
55206  *  Helpers to resize properties allocation on specific needs.
55207  */
55208 
55209 DUK_INTERNAL void duk_hobject_resize_entrypart(duk_hthread *thr,
55210                                                duk_hobject *obj,
55211                                                duk_uint32_t new_e_size) {
55212 	duk_uint32_t old_e_size;
55213 	duk_uint32_t new_a_size;
55214 	duk_uint32_t new_h_size;
55215 
55216 	DUK_ASSERT(thr != NULL);
55217 	DUK_ASSERT(obj != NULL);
55218 
55219 	old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55220 	if (old_e_size > new_e_size) {
55221 		new_e_size = old_e_size;
55222 	}
55223 #if defined(DUK_USE_HOBJECT_HASH_PART)
55224 	new_h_size = duk__get_default_h_size(new_e_size);
55225 #else
55226 	new_h_size = 0;
55227 #endif
55228 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55229 
55230 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55231 }
55232 
55233 #if 0  /*unused */
55234 DUK_INTERNAL void duk_hobject_resize_arraypart(duk_hthread *thr,
55235                                                duk_hobject *obj,
55236                                                duk_uint32_t new_a_size) {
55237 	duk_uint32_t old_a_size;
55238 	duk_uint32_t new_e_size;
55239 	duk_uint32_t new_h_size;
55240 
55241 	DUK_ASSERT(thr != NULL);
55242 	DUK_ASSERT(obj != NULL);
55243 
55244 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55245 		return;
55246 	}
55247 	old_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55248 	if (old_a_size > new_a_size) {
55249 		new_a_size = old_a_size;
55250 	}
55251 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55252 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
55253 
55254 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55255 }
55256 #endif
55257 
55258 /* Grow entry part allocation for one additional entry. */
55259 DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
55260 	duk_uint32_t old_e_used;  /* actually used, non-NULL entries */
55261 	duk_uint32_t new_e_size;
55262 	duk_uint32_t new_a_size;
55263 	duk_uint32_t new_h_size;
55264 
55265 	DUK_ASSERT(thr != NULL);
55266 	DUK_ASSERT(obj != NULL);
55267 
55268 	/* Duktape 0.11.0 and prior tried to optimize the resize by not
55269 	 * counting the number of actually used keys prior to the resize.
55270 	 * This worked mostly well but also caused weird leak-like behavior
55271 	 * as in: test-bug-object-prop-alloc-unbounded.js.  So, now we count
55272 	 * the keys explicitly to compute the new entry part size.
55273 	 */
55274 
55275 	old_e_used = duk__count_used_e_keys(thr, obj);
55276 	new_e_size = old_e_used + duk__get_min_grow_e(old_e_used);
55277 #if defined(DUK_USE_HOBJECT_HASH_PART)
55278 	new_h_size = duk__get_default_h_size(new_e_size);
55279 #else
55280 	new_h_size = 0;
55281 #endif
55282 	new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
55283 	DUK_ASSERT(new_e_size >= old_e_used + 1);  /* duk__get_min_grow_e() is always >= 1 */
55284 
55285 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55286 }
55287 
55288 /* Grow array part for a new highest array index. */
55289 DUK_LOCAL void duk__grow_props_for_array_item(duk_hthread *thr, duk_hobject *obj, duk_uint32_t highest_arr_idx) {
55290 	duk_uint32_t new_e_size;
55291 	duk_uint32_t new_a_size;
55292 	duk_uint32_t new_h_size;
55293 
55294 	DUK_ASSERT(thr != NULL);
55295 	DUK_ASSERT(obj != NULL);
55296 	DUK_ASSERT(highest_arr_idx >= DUK_HOBJECT_GET_ASIZE(obj));
55297 
55298 	/* minimum new length is highest_arr_idx + 1 */
55299 
55300 	new_e_size = DUK_HOBJECT_GET_ESIZE(obj);
55301 	new_h_size = DUK_HOBJECT_GET_HSIZE(obj);
55302 	new_a_size = highest_arr_idx + duk__get_min_grow_a(highest_arr_idx);
55303 	DUK_ASSERT(new_a_size >= highest_arr_idx + 1);  /* duk__get_min_grow_a() is always >= 1 */
55304 
55305 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
55306 }
55307 
55308 /* Abandon array part, moving array entries into entries part.
55309  * This requires a props resize, which is a heavy operation.
55310  * We also compact the entries part while we're at it, although
55311  * this is not strictly required.
55312  */
55313 DUK_LOCAL void duk__abandon_array_checked(duk_hthread *thr, duk_hobject *obj) {
55314 	duk_uint32_t new_e_size;
55315 	duk_uint32_t new_a_size;
55316 	duk_uint32_t new_h_size;
55317 	duk_uint32_t e_used;  /* actually used, non-NULL keys */
55318 	duk_uint32_t a_used;
55319 	duk_uint32_t a_size;
55320 
55321 	DUK_ASSERT(thr != NULL);
55322 	DUK_ASSERT(obj != NULL);
55323 
55324 	e_used = duk__count_used_e_keys(thr, obj);
55325 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55326 
55327 	/*
55328 	 *  Must guarantee all actually used array entries will fit into
55329 	 *  new entry part.  Add one growth step to ensure we don't run out
55330 	 *  of space right away.
55331 	 */
55332 
55333 	new_e_size = e_used + a_used;
55334 	new_e_size = new_e_size + duk__get_min_grow_e(new_e_size);
55335 	new_a_size = 0;
55336 #if defined(DUK_USE_HOBJECT_HASH_PART)
55337 	new_h_size = duk__get_default_h_size(new_e_size);
55338 #else
55339 	new_h_size = 0;
55340 #endif
55341 
55342 	DUK_DD(DUK_DDPRINT("abandon array part for hobject %p, "
55343 	                   "array stats before: e_used=%ld, a_used=%ld, a_size=%ld; "
55344 	                   "resize to e_size=%ld, a_size=%ld, h_size=%ld",
55345 	                   (void *) obj, (long) e_used, (long) a_used, (long) a_size,
55346 	                   (long) new_e_size, (long) new_a_size, (long) new_h_size));
55347 
55348 	duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 1);
55349 }
55350 
55351 /*
55352  *  Compact an object.  Minimizes allocation size for objects which are
55353  *  not likely to be extended.  This is useful for internal and non-
55354  *  extensible objects, but can also be called for non-extensible objects.
55355  *  May abandon the array part if it is computed to be too sparse.
55356  *
55357  *  This call is relatively expensive, as it needs to scan both the
55358  *  entries and the array part.
55359  *
55360  *  The call may fail due to allocation error.
55361  */
55362 
55363 DUK_INTERNAL void duk_hobject_compact_props(duk_hthread *thr, duk_hobject *obj) {
55364 	duk_uint32_t e_size;       /* currently used -> new size */
55365 	duk_uint32_t a_size;       /* currently required */
55366 	duk_uint32_t a_used;       /* actually used */
55367 	duk_uint32_t h_size;
55368 	duk_bool_t abandon_array;
55369 
55370 	DUK_ASSERT(thr != NULL);
55371 	DUK_ASSERT(obj != NULL);
55372 
55373 #if defined(DUK_USE_ROM_OBJECTS)
55374 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
55375 		DUK_DD(DUK_DDPRINT("ignore attempt to compact a rom object"));
55376 		return;
55377 	}
55378 #endif
55379 
55380 	e_size = duk__count_used_e_keys(thr, obj);
55381 	duk__compute_a_stats(thr, obj, &a_used, &a_size);
55382 
55383 	DUK_DD(DUK_DDPRINT("compacting hobject, used e keys %ld, used a keys %ld, min a size %ld, "
55384 	                   "resized array density would be: %ld/%ld = %lf",
55385 	                   (long) e_size, (long) a_used, (long) a_size,
55386 	                   (long) a_used, (long) a_size,
55387 	                   (double) a_used / (double) a_size));
55388 
55389 	if (duk__abandon_array_density_check(a_used, a_size)) {
55390 		DUK_DD(DUK_DDPRINT("decided to abandon array during compaction, a_used=%ld, a_size=%ld",
55391 		                   (long) a_used, (long) a_size));
55392 		abandon_array = 1;
55393 		e_size += a_used;
55394 		a_size = 0;
55395 	} else {
55396 		DUK_DD(DUK_DDPRINT("decided to keep array during compaction"));
55397 		abandon_array = 0;
55398 	}
55399 
55400 #if defined(DUK_USE_HOBJECT_HASH_PART)
55401 	if (e_size >= DUK_USE_HOBJECT_HASH_PROP_LIMIT) {
55402 		h_size = duk__get_default_h_size(e_size);
55403 	} else {
55404 		h_size = 0;
55405 	}
55406 #else
55407 	h_size = 0;
55408 #endif
55409 
55410 	DUK_DD(DUK_DDPRINT("compacting hobject -> new e_size %ld, new a_size=%ld, new h_size=%ld, abandon_array=%ld",
55411 	                   (long) e_size, (long) a_size, (long) h_size, (long) abandon_array));
55412 
55413 	duk_hobject_realloc_props(thr, obj, e_size, a_size, h_size, abandon_array);
55414 }
55415 
55416 /*
55417  *  Find an existing key from entry part either by linear scan or by
55418  *  using the hash index (if it exists).
55419  *
55420  *  Sets entry index (and possibly the hash index) to output variables,
55421  *  which allows the caller to update the entry and hash entries in-place.
55422  *  If entry is not found, both values are set to -1.  If entry is found
55423  *  but there is no hash part, h_idx is set to -1.
55424  */
55425 
55426 DUK_INTERNAL duk_bool_t duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx) {
55427 	DUK_ASSERT(obj != NULL);
55428 	DUK_ASSERT(key != NULL);
55429 	DUK_ASSERT(e_idx != NULL);
55430 	DUK_ASSERT(h_idx != NULL);
55431 	DUK_UNREF(heap);
55432 
55433 	if (DUK_LIKELY(DUK_HOBJECT_GET_HSIZE(obj) == 0))
55434 	{
55435 		/* Linear scan: more likely because most objects are small.
55436 		 * This is an important fast path.
55437 		 *
55438 		 * XXX: this might be worth inlining for property lookups.
55439 		 */
55440 		duk_uint_fast32_t i;
55441 		duk_uint_fast32_t n;
55442 		duk_hstring **h_keys_base;
55443 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using linear scan for lookup"));
55444 
55445 		h_keys_base = DUK_HOBJECT_E_GET_KEY_BASE(heap, obj);
55446 		n = DUK_HOBJECT_GET_ENEXT(obj);
55447 		for (i = 0; i < n; i++) {
55448 			if (h_keys_base[i] == key) {
55449 				*e_idx = (duk_int_t) i;
55450 				*h_idx = -1;
55451 				return 1;
55452 			}
55453 		}
55454 	}
55455 #if defined(DUK_USE_HOBJECT_HASH_PART)
55456 	else
55457 	{
55458 		/* hash lookup */
55459 		duk_uint32_t n;
55460 		duk_uint32_t i, step;
55461 		duk_uint32_t *h_base;
55462 		duk_uint32_t mask;
55463 
55464 		DUK_DDD(DUK_DDDPRINT("duk_hobject_find_existing_entry() using hash part for lookup"));
55465 
55466 		h_base = DUK_HOBJECT_H_GET_BASE(heap, obj);
55467 		n = DUK_HOBJECT_GET_HSIZE(obj);
55468 		mask = n - 1;
55469 		i = DUK_HSTRING_GET_HASH(key) & mask;
55470 		step = 1;  /* Cache friendly but clustering prone. */
55471 
55472 		for (;;) {
55473 			duk_uint32_t t;
55474 
55475 			DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
55476 			DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
55477 			t = h_base[i];
55478 			DUK_ASSERT(t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED ||
55479 			           (t < DUK_HOBJECT_GET_ESIZE(obj)));  /* t >= 0 always true, unsigned */
55480 
55481 			if (t == DUK__HASH_UNUSED) {
55482 				break;
55483 			} else if (t == DUK__HASH_DELETED) {
55484 				DUK_DDD(DUK_DDDPRINT("lookup miss (deleted) i=%ld, t=%ld",
55485 				                     (long) i, (long) t));
55486 			} else {
55487 				DUK_ASSERT(t < DUK_HOBJECT_GET_ESIZE(obj));
55488 				if (DUK_HOBJECT_E_GET_KEY(heap, obj, t) == key) {
55489 					DUK_DDD(DUK_DDDPRINT("lookup hit i=%ld, t=%ld -> key %p",
55490 					                     (long) i, (long) t, (void *) key));
55491 					*e_idx = (duk_int_t) t;
55492 					*h_idx = (duk_int_t) i;
55493 					return 1;
55494 				}
55495 				DUK_DDD(DUK_DDDPRINT("lookup miss i=%ld, t=%ld",
55496 				                     (long) i, (long) t));
55497 			}
55498 			i = (i + step) & mask;
55499 
55500 			/* Guaranteed to finish (hash is larger than #props). */
55501 		}
55502 	}
55503 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55504 
55505 	/* Not found, leave e_idx and h_idx unset. */
55506 	return 0;
55507 }
55508 
55509 /* For internal use: get non-accessor entry value */
55510 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_hstring *key) {
55511 	duk_int_t e_idx;
55512 	duk_int_t h_idx;
55513 
55514 	DUK_ASSERT(obj != NULL);
55515 	DUK_ASSERT(key != NULL);
55516 	DUK_UNREF(heap);
55517 
55518 	if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
55519 		DUK_ASSERT(e_idx >= 0);
55520 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
55521 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
55522 		}
55523 	}
55524 	return NULL;
55525 }
55526 
55527 /* For internal use: get non-accessor entry value and attributes */
55528 DUK_INTERNAL duk_tval *duk_hobject_find_existing_entry_tval_ptr_and_attrs(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_uint_t *out_attrs) {
55529 	duk_int_t e_idx;
55530 	duk_int_t h_idx;
55531 
55532 	DUK_ASSERT(obj != NULL);
55533 	DUK_ASSERT(key != NULL);
55534 	DUK_ASSERT(out_attrs != NULL);
55535 	DUK_UNREF(heap);
55536 
55537 	if (duk_hobject_find_existing_entry(heap, obj, key, &e_idx, &h_idx)) {
55538 		DUK_ASSERT(e_idx >= 0);
55539 		if (!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx)) {
55540 			*out_attrs = DUK_HOBJECT_E_GET_FLAGS(heap, obj, e_idx);
55541 			return DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx);
55542 		}
55543 	}
55544 	/* If not found, out_attrs is left unset. */
55545 	return NULL;
55546 }
55547 
55548 /* For internal use: get array part value */
55549 DUK_INTERNAL duk_tval *duk_hobject_find_existing_array_entry_tval_ptr(duk_heap *heap, duk_hobject *obj, duk_uarridx_t i) {
55550 	duk_tval *tv;
55551 
55552 	DUK_ASSERT(obj != NULL);
55553 	DUK_UNREF(heap);
55554 
55555 	if (!DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
55556 		return NULL;
55557 	}
55558 	if (i >= DUK_HOBJECT_GET_ASIZE(obj)) {
55559 		return NULL;
55560 	}
55561 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(heap, obj, i);
55562 	return tv;
55563 }
55564 
55565 /*
55566  *  Allocate and initialize a new entry, resizing the properties allocation
55567  *  if necessary.  Returns entry index (e_idx) or throws an error if alloc fails.
55568  *
55569  *  Sets the key of the entry (increasing the key's refcount), and updates
55570  *  the hash part if it exists.  Caller must set value and flags, and update
55571  *  the entry value refcount.  A decref for the previous value is not necessary.
55572  */
55573 
55574 DUK_LOCAL duk_int_t duk__hobject_alloc_entry_checked(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
55575 	duk_uint32_t idx;
55576 
55577 	DUK_ASSERT(thr != NULL);
55578 	DUK_ASSERT(obj != NULL);
55579 	DUK_ASSERT(key != NULL);
55580 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) <= DUK_HOBJECT_GET_ESIZE(obj));
55581 
55582 #if defined(DUK_USE_ASSERTIONS)
55583 	/* key must not already exist in entry part */
55584 	{
55585 		duk_uint_fast32_t i;
55586 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
55587 			DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != key);
55588 		}
55589 	}
55590 #endif
55591 
55592 	if (DUK_HOBJECT_GET_ENEXT(obj) >= DUK_HOBJECT_GET_ESIZE(obj)) {
55593 		/* only need to guarantee 1 more slot, but allocation growth is in chunks */
55594 		DUK_DDD(DUK_DDDPRINT("entry part full, allocate space for one more entry"));
55595 		duk__grow_props_for_new_entry_item(thr, obj);
55596 	}
55597 	DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(obj) < DUK_HOBJECT_GET_ESIZE(obj));
55598 	idx = DUK_HOBJECT_POSTINC_ENEXT(obj);
55599 
55600 	/* previous value is assumed to be garbage, so don't touch it */
55601 	DUK_HOBJECT_E_SET_KEY(thr->heap, obj, idx, key);
55602 	DUK_HSTRING_INCREF(thr, key);
55603 
55604 #if defined(DUK_USE_HOBJECT_HASH_PART)
55605 	if (DUK_UNLIKELY(DUK_HOBJECT_GET_HSIZE(obj) > 0)) {
55606 		duk_uint32_t n, mask;
55607 		duk_uint32_t i, step;
55608 		duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
55609 
55610 		n = DUK_HOBJECT_GET_HSIZE(obj);
55611 		mask = n - 1;
55612 		i = DUK_HSTRING_GET_HASH(key) & mask;
55613 		step = 1;  /* Cache friendly but clustering prone. */
55614 
55615 		for (;;) {
55616 			duk_uint32_t t = h_base[i];
55617 			if (t == DUK__HASH_UNUSED || t == DUK__HASH_DELETED) {
55618 				DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() inserted key into hash part, %ld -> %ld",
55619 				                     (long) i, (long) idx));
55620 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
55621 				DUK_ASSERT(i < DUK_HOBJECT_GET_HSIZE(obj));
55622 				DUK_ASSERT_DISABLE(idx >= 0);
55623 				DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
55624 				h_base[i] = idx;
55625 				break;
55626 			}
55627 			DUK_DDD(DUK_DDDPRINT("duk__hobject_alloc_entry_checked() miss %ld", (long) i));
55628 			i = (i + step) & mask;
55629 
55630 			/* Guaranteed to finish (hash is larger than #props). */
55631 		}
55632 	}
55633 #endif  /* DUK_USE_HOBJECT_HASH_PART */
55634 
55635 	/* Note: we could return the hash index here too, but it's not
55636 	 * needed right now.
55637 	 */
55638 
55639 	DUK_ASSERT_DISABLE(idx >= 0);
55640 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ESIZE(obj));
55641 	DUK_ASSERT(idx < DUK_HOBJECT_GET_ENEXT(obj));
55642 	return (duk_int_t) idx;
55643 }
55644 
55645 /*
55646  *  Object internal value
55647  *
55648  *  Returned value is guaranteed to be reachable / incref'd, caller does not need
55649  *  to incref OR decref.  No proxies or accessors are invoked, no prototype walk.
55650  */
55651 
55652 DUK_INTERNAL duk_bool_t duk_hobject_get_internal_value(duk_heap *heap, duk_hobject *obj, duk_tval *tv_out) {
55653 	duk_int_t e_idx;
55654 	duk_int_t h_idx;
55655 
55656 	DUK_ASSERT(heap != NULL);
55657 	DUK_ASSERT(obj != NULL);
55658 	DUK_ASSERT(tv_out != NULL);
55659 
55660 	/* Always in entry part, no need to look up parents etc. */
55661 	if (duk_hobject_find_existing_entry(heap, obj, DUK_HEAP_STRING_INT_VALUE(heap), &e_idx, &h_idx)) {
55662 		DUK_ASSERT(e_idx >= 0);
55663 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(heap, obj, e_idx));
55664 		DUK_TVAL_SET_TVAL(tv_out, DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(heap, obj, e_idx));
55665 		return 1;
55666 	}
55667 	DUK_TVAL_SET_UNDEFINED(tv_out);
55668 	return 0;
55669 }
55670 
55671 DUK_INTERNAL duk_hstring *duk_hobject_get_internal_value_string(duk_heap *heap, duk_hobject *obj) {
55672 	duk_tval tv;
55673 
55674 	DUK_ASSERT(heap != NULL);
55675 	DUK_ASSERT(obj != NULL);
55676 
55677 	/* This is not strictly necessary, but avoids compiler warnings; e.g.
55678 	 * gcc won't reliably detect that no uninitialized data is read below.
55679 	 */
55680 	duk_memzero((void *) &tv, sizeof(duk_tval));
55681 
55682 	if (duk_hobject_get_internal_value(heap, obj, &tv)) {
55683 		duk_hstring *h;
55684 		DUK_ASSERT(DUK_TVAL_IS_STRING(&tv));
55685 		h = DUK_TVAL_GET_STRING(&tv);
55686 		/* No explicit check for string vs. symbol, accept both. */
55687 		return h;
55688 	}
55689 
55690 	return NULL;
55691 }
55692 
55693 /*
55694  *  Arguments handling helpers (argument map mainly).
55695  *
55696  *  An arguments object has exotic behavior for some numeric indices.
55697  *  Accesses may translate to identifier operations which may have
55698  *  arbitrary side effects (potentially invalidating any duk_tval
55699  *  pointers).
55700  */
55701 
55702 /* Lookup 'key' from arguments internal 'map', perform a variable lookup
55703  * if mapped, and leave the result on top of stack (and return non-zero).
55704  * Used in E5 Section 10.6 algorithms [[Get]] and [[GetOwnProperty]].
55705  */
55706 DUK_LOCAL
55707 duk_bool_t duk__lookup_arguments_map(duk_hthread *thr,
55708                                      duk_hobject *obj,
55709                                      duk_hstring *key,
55710                                      duk_propdesc *temp_desc,
55711                                      duk_hobject **out_map,
55712                                      duk_hobject **out_varenv) {
55713 	duk_hobject *map;
55714 	duk_hobject *varenv;
55715 	duk_bool_t rc;
55716 
55717 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55718 
55719 	DUK_DDD(DUK_DDDPRINT("arguments map lookup: thr=%p, obj=%p, key=%p, temp_desc=%p "
55720 	                     "(obj -> %!O, key -> %!O)",
55721 	                     (void *) thr, (void *) obj, (void *) key, (void *) temp_desc,
55722 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
55723 
55724 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55725 		DUK_DDD(DUK_DDDPRINT("-> no 'map'"));
55726 		return 0;
55727 	}
55728 
55729 	map = duk_require_hobject(thr, -1);
55730 	DUK_ASSERT(map != NULL);
55731 	duk_pop_unsafe(thr);  /* map is reachable through obj */
55732 
55733 	if (!duk_hobject_get_own_propdesc(thr, map, key, temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55734 		DUK_DDD(DUK_DDDPRINT("-> 'map' exists, but key not in map"));
55735 		return 0;
55736 	}
55737 
55738 	/* [... varname] */
55739 	DUK_DDD(DUK_DDDPRINT("-> 'map' exists, and contains key, key is mapped to argument/variable binding %!T",
55740 	                     (duk_tval *) duk_get_tval(thr, -1)));
55741 	DUK_ASSERT(duk_is_string(thr, -1));  /* guaranteed when building arguments */
55742 
55743 	/* get varenv for varname (callee's declarative lexical environment) */
55744 	rc = duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_VARENV(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE);
55745 	DUK_UNREF(rc);
55746 	DUK_ASSERT(rc != 0);  /* arguments MUST have an initialized lexical environment reference */
55747 	varenv = duk_require_hobject(thr, -1);
55748 	DUK_ASSERT(varenv != NULL);
55749 	duk_pop_unsafe(thr);  /* varenv remains reachable through 'obj' */
55750 
55751 	DUK_DDD(DUK_DDDPRINT("arguments varenv is: %!dO", (duk_heaphdr *) varenv));
55752 
55753 	/* success: leave varname in stack */
55754 	*out_map = map;
55755 	*out_varenv = varenv;
55756 	return 1;  /* [... varname] */
55757 }
55758 
55759 /* Lookup 'key' from arguments internal 'map', and leave replacement value
55760  * on stack top if mapped (and return non-zero).
55761  * Used in E5 Section 10.6 algorithm for [[GetOwnProperty]] (used by [[Get]]).
55762  */
55763 DUK_LOCAL duk_bool_t duk__check_arguments_map_for_get(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
55764 	duk_hobject *map;
55765 	duk_hobject *varenv;
55766 	duk_hstring *varname;
55767 
55768 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55769 
55770 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
55771 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic get behavior"));
55772 		return 0;
55773 	}
55774 
55775 	/* [... varname] */
55776 
55777 	varname = duk_require_hstring(thr, -1);
55778 	DUK_ASSERT(varname != NULL);
55779 	duk_pop_unsafe(thr);  /* varname is still reachable */
55780 
55781 	DUK_DDD(DUK_DDDPRINT("arguments object automatic getvar for a bound variable; "
55782 	                     "key=%!O, varname=%!O",
55783 	                     (duk_heaphdr *) key,
55784 	                     (duk_heaphdr *) varname));
55785 
55786 	(void) duk_js_getvar_envrec(thr, varenv, varname, 1 /*throw*/);
55787 
55788 	/* [... value this_binding] */
55789 
55790 	duk_pop_unsafe(thr);
55791 
55792 	/* leave result on stack top */
55793 	return 1;
55794 }
55795 
55796 /* Lookup 'key' from arguments internal 'map', perform a variable write if mapped.
55797  * Used in E5 Section 10.6 algorithm for [[DefineOwnProperty]] (used by [[Put]]).
55798  * Assumes stack top contains 'put' value (which is NOT popped).
55799  */
55800 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) {
55801 	duk_hobject *map;
55802 	duk_hobject *varenv;
55803 	duk_hstring *varname;
55804 
55805 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55806 
55807 	if (!duk__lookup_arguments_map(thr, obj, key, temp_desc, &map, &varenv)) {
55808 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic put behavior"));
55809 		return;
55810 	}
55811 
55812 	/* [... put_value varname] */
55813 
55814 	varname = duk_require_hstring(thr, -1);
55815 	DUK_ASSERT(varname != NULL);
55816 	duk_pop_unsafe(thr);  /* varname is still reachable */
55817 
55818 	DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
55819 	                     "key=%!O, varname=%!O, value=%!T",
55820 	                     (duk_heaphdr *) key,
55821 	                     (duk_heaphdr *) varname,
55822 	                     (duk_tval *) duk_require_tval(thr, -1)));
55823 
55824 	/* [... put_value] */
55825 
55826 	/*
55827 	 *  Note: although arguments object variable mappings are only established
55828 	 *  for non-strict functions (and a call to a non-strict function created
55829 	 *  the arguments object in question), an inner strict function may be doing
55830 	 *  the actual property write.  Hence the throw_flag applied here comes from
55831 	 *  the property write call.
55832 	 */
55833 
55834 	duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, -1), throw_flag);
55835 
55836 	/* [... put_value] */
55837 }
55838 
55839 /* Lookup 'key' from arguments internal 'map', delete mapping if found.
55840  * Used in E5 Section 10.6 algorithm for [[Delete]].  Note that the
55841  * variable/argument itself (where the map points) is not deleted.
55842  */
55843 DUK_LOCAL void duk__check_arguments_map_for_delete(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_propdesc *temp_desc) {
55844 	duk_hobject *map;
55845 
55846 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55847 
55848 	if (!duk_hobject_get_own_propdesc(thr, obj, DUK_HTHREAD_STRING_INT_MAP(thr), temp_desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
55849 		DUK_DDD(DUK_DDDPRINT("arguments: key not mapped, no exotic delete behavior"));
55850 		return;
55851 	}
55852 
55853 	map = duk_require_hobject(thr, -1);
55854 	DUK_ASSERT(map != NULL);
55855 	duk_pop_unsafe(thr);  /* map is reachable through obj */
55856 
55857 	DUK_DDD(DUK_DDDPRINT("-> have 'map', delete key %!O from map (if exists)); ignore result",
55858 	                     (duk_heaphdr *) key));
55859 
55860 	/* Note: no recursion issue, we can trust 'map' to behave */
55861 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_BEHAVIOR(map));
55862 	DUK_DDD(DUK_DDDPRINT("map before deletion: %!O", (duk_heaphdr *) map));
55863 	(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
55864 	DUK_DDD(DUK_DDDPRINT("map after deletion: %!O", (duk_heaphdr *) map));
55865 }
55866 
55867 /*
55868  *  ECMAScript compliant [[GetOwnProperty]](P), for internal use only.
55869  *
55870  *  If property is found:
55871  *    - Fills descriptor fields to 'out_desc'
55872  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
55873  *      property onto the stack ('undefined' for accessor properties).
55874  *    - Returns non-zero
55875  *
55876  *  If property is not found:
55877  *    - 'out_desc' is left in untouched state (possibly garbage)
55878  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
55879  *      set)
55880  *    - Returns zero
55881  *
55882  *  Notes:
55883  *
55884  *    - Getting a property descriptor may cause an allocation (and hence
55885  *      GC) to take place, hence reachability and refcount of all related
55886  *      values matter.  Reallocation of value stack, properties, etc may
55887  *      invalidate many duk_tval pointers (concretely, those which reside
55888  *      in memory areas subject to reallocation).  However, heap object
55889  *      pointers are never affected (heap objects have stable pointers).
55890  *
55891  *    - The value of a plain property is always reachable and has a non-zero
55892  *      reference count.
55893  *
55894  *    - The value of a virtual property is not necessarily reachable from
55895  *      elsewhere and may have a refcount of zero.  Hence we push it onto
55896  *      the valstack for the caller, which ensures it remains reachable
55897  *      while it is needed.
55898  *
55899  *    - There are no virtual accessor properties.  Hence, all getters and
55900  *      setters are always related to concretely stored properties, which
55901  *      ensures that the get/set functions in the resulting descriptor are
55902  *      reachable and have non-zero refcounts.  Should there be virtual
55903  *      accessor properties later, this would need to change.
55904  */
55905 
55906 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) {
55907 	duk_tval *tv;
55908 
55909 	DUK_DDD(DUK_DDDPRINT("duk_hobject_get_own_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
55910 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
55911 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
55912 	                     (long) flags, (long) arr_idx,
55913 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
55914 
55915 	DUK_ASSERT(thr != NULL);
55916 	DUK_ASSERT(thr->heap != NULL);
55917 	DUK_ASSERT(obj != NULL);
55918 	DUK_ASSERT(key != NULL);
55919 	DUK_ASSERT(out_desc != NULL);
55920 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
55921 
55922 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_count);
55923 
55924 	/* Each code path returning 1 (= found) must fill in all the output
55925 	 * descriptor fields.  We don't do it beforehand because it'd be
55926 	 * unnecessary work if the property isn't found and would happen
55927 	 * multiple times for an inheritance chain.
55928 	 */
55929 	DUK_ASSERT_SET_GARBAGE(out_desc, sizeof(*out_desc));
55930 #if 0
55931 	out_desc->flags = 0;
55932 	out_desc->get = NULL;
55933 	out_desc->set = NULL;
55934 	out_desc->e_idx = -1;
55935 	out_desc->h_idx = -1;
55936 	out_desc->a_idx = -1;
55937 #endif
55938 
55939 	/*
55940 	 *  Try entries part first because it's the common case.
55941 	 *
55942 	 *  Array part lookups are usually handled by the array fast path, and
55943 	 *  are not usually inherited.  Array and entry parts never contain the
55944 	 *  same keys so the entry part vs. array part order doesn't matter.
55945 	 */
55946 
55947 	if (duk_hobject_find_existing_entry(thr->heap, obj, key, &out_desc->e_idx, &out_desc->h_idx)) {
55948 		duk_int_t e_idx = out_desc->e_idx;
55949 		DUK_ASSERT(out_desc->e_idx >= 0);
55950 		out_desc->a_idx = -1;
55951 		out_desc->flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, e_idx);
55952 		out_desc->get = NULL;
55953 		out_desc->set = NULL;
55954 		if (DUK_UNLIKELY(out_desc->flags & DUK_PROPDESC_FLAG_ACCESSOR)) {
55955 			DUK_DDD(DUK_DDDPRINT("-> found accessor property in entry part"));
55956 			out_desc->get = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, e_idx);
55957 			out_desc->set = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, e_idx);
55958 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55959 				/* a dummy undefined value is pushed to make valstack
55960 				 * behavior uniform for caller
55961 				 */
55962 				duk_push_undefined(thr);
55963 			}
55964 		} else {
55965 			DUK_DDD(DUK_DDDPRINT("-> found plain property in entry part"));
55966 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
55967 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55968 				duk_push_tval(thr, tv);
55969 			}
55970 		}
55971 		goto prop_found;
55972 	}
55973 
55974 	/*
55975 	 *  Try array part.
55976 	 */
55977 
55978 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) && arr_idx != DUK__NO_ARRAY_INDEX) {
55979 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(obj)) {
55980 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
55981 			if (!DUK_TVAL_IS_UNUSED(tv)) {
55982 				DUK_DDD(DUK_DDDPRINT("-> found in array part"));
55983 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
55984 					duk_push_tval(thr, tv);
55985 				}
55986 				/* implicit attributes */
55987 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
55988 				                  DUK_PROPDESC_FLAG_CONFIGURABLE |
55989 				                  DUK_PROPDESC_FLAG_ENUMERABLE;
55990 				out_desc->get = NULL;
55991 				out_desc->set = NULL;
55992 				out_desc->e_idx = -1;
55993 				out_desc->h_idx = -1;
55994 				out_desc->a_idx = (duk_int_t) arr_idx;  /* XXX: limit 2G due to being signed */
55995 				goto prop_found;
55996 			}
55997 		}
55998 	}
55999 
56000 	DUK_DDD(DUK_DDDPRINT("-> not found as a concrete property"));
56001 
56002 	/*
56003 	 *  Not found as a concrete property, check for virtual properties.
56004 	 */
56005 
56006 	if (!DUK_HOBJECT_HAS_VIRTUAL_PROPERTIES(obj)) {
56007 		/* Quick skip. */
56008 		goto prop_not_found;
56009 	}
56010 
56011 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
56012 		duk_harray *a;
56013 
56014 		DUK_DDD(DUK_DDDPRINT("array object exotic property get for key: %!O, arr_idx: %ld",
56015 		                     (duk_heaphdr *) key, (long) arr_idx));
56016 
56017 		a = (duk_harray *) obj;
56018 		DUK_ASSERT_HARRAY_VALID(a);
56019 
56020 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56021 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56022 
56023 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56024 				duk_push_uint(thr, (duk_uint_t) a->length);
56025 			}
56026 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56027 			if (DUK_HARRAY_LENGTH_WRITABLE(a)) {
56028 				out_desc->flags |= DUK_PROPDESC_FLAG_WRITABLE;
56029 			}
56030 			out_desc->get = NULL;
56031 			out_desc->set = NULL;
56032 			out_desc->e_idx = -1;
56033 			out_desc->h_idx = -1;
56034 			out_desc->a_idx = -1;
56035 
56036 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56037 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56038 		}
56039 	} else if (DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj)) {
56040 		DUK_DDD(DUK_DDDPRINT("string object exotic property get for key: %!O, arr_idx: %ld",
56041 		                     (duk_heaphdr *) key, (long) arr_idx));
56042 
56043 		/* XXX: charlen; avoid multiple lookups? */
56044 
56045 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
56046 			duk_hstring *h_val;
56047 
56048 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56049 
56050 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56051 			DUK_ASSERT(h_val);
56052 			if (arr_idx < DUK_HSTRING_GET_CHARLEN(h_val)) {
56053 				DUK_DDD(DUK_DDDPRINT("-> found, array index inside string"));
56054 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56055 					duk_push_hstring(thr, h_val);
56056 					duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
56057 				}
56058 				out_desc->flags = DUK_PROPDESC_FLAG_ENUMERABLE |  /* E5 Section 15.5.5.2 */
56059 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56060 				out_desc->get = NULL;
56061 				out_desc->set = NULL;
56062 				out_desc->e_idx = -1;
56063 				out_desc->h_idx = -1;
56064 				out_desc->a_idx = -1;
56065 
56066 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56067 				goto prop_found_noexotic;  /* cannot be arguments exotic */
56068 			} else {
56069 				/* index is above internal string length -> property is fully normal */
56070 				DUK_DDD(DUK_DDDPRINT("array index outside string -> normal property"));
56071 			}
56072 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56073 			duk_hstring *h_val;
56074 
56075 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56076 
56077 			h_val = duk_hobject_get_internal_value_string(thr->heap, obj);
56078 			DUK_ASSERT(h_val != NULL);
56079 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56080 				duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h_val));
56081 			}
56082 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;  /* E5 Section 15.5.5.1 */
56083 			out_desc->get = NULL;
56084 			out_desc->set = NULL;
56085 			out_desc->e_idx = -1;
56086 			out_desc->h_idx = -1;
56087 			out_desc->a_idx = -1;
56088 
56089 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56090 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56091 		}
56092 	}
56093 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56094 	else if (DUK_HOBJECT_IS_BUFOBJ(obj)) {
56095 		duk_hbufobj *h_bufobj;
56096 		duk_uint_t byte_off;
56097 		duk_small_uint_t elem_size;
56098 
56099 		h_bufobj = (duk_hbufobj *) obj;
56100 		DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
56101 		DUK_DDD(DUK_DDDPRINT("bufobj property get for key: %!O, arr_idx: %ld",
56102 		                     (duk_heaphdr *) key, (long) arr_idx));
56103 
56104 		if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56105 			DUK_DDD(DUK_DDDPRINT("array index exists"));
56106 
56107 			/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
56108 			 * length downshift won't.
56109 			 */
56110 			if (arr_idx < (h_bufobj->length >> h_bufobj->shift)) {
56111 				byte_off = arr_idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56112 				elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56113 				if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56114 					duk_uint8_t *data;
56115 
56116 					if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56117 						data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56118 						duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
56119 					} else {
56120 						DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
56121 						duk_push_uint(thr, 0);
56122 					}
56123 				}
56124 				out_desc->flags = DUK_PROPDESC_FLAG_WRITABLE |
56125 				                  DUK_PROPDESC_FLAG_VIRTUAL;
56126 				if (DUK_HOBJECT_GET_CLASS_NUMBER(obj) != DUK_HOBJECT_CLASS_ARRAYBUFFER) {
56127 					/* ArrayBuffer indices are non-standard and are
56128 					 * non-enumerable to avoid their serialization.
56129 					 */
56130 					out_desc->flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
56131 				}
56132 				out_desc->get = NULL;
56133 				out_desc->set = NULL;
56134 				out_desc->e_idx = -1;
56135 				out_desc->h_idx = -1;
56136 				out_desc->a_idx = -1;
56137 
56138 				DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56139 				goto prop_found_noexotic;  /* cannot be e.g. arguments exotic, since exotic 'traits' are mutually exclusive */
56140 			} else {
56141 				/* index is above internal buffer length -> property is fully normal */
56142 				DUK_DDD(DUK_DDDPRINT("array index outside buffer -> normal property"));
56143 			}
56144 		} else if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56145 			DUK_DDD(DUK_DDDPRINT("-> found, key is 'length', length exotic behavior"));
56146 
56147 			if (flags & DUK_GETDESC_FLAG_PUSH_VALUE) {
56148 				/* Length in elements: take into account shift, but
56149 				 * intentionally don't check the underlying buffer here.
56150 				 */
56151 				duk_push_uint(thr, h_bufobj->length >> h_bufobj->shift);
56152 			}
56153 			out_desc->flags = DUK_PROPDESC_FLAG_VIRTUAL;
56154 			out_desc->get = NULL;
56155 			out_desc->set = NULL;
56156 			out_desc->e_idx = -1;
56157 			out_desc->h_idx = -1;
56158 			out_desc->a_idx = -1;
56159 
56160 			DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj));
56161 			goto prop_found_noexotic;  /* cannot be arguments exotic */
56162 		}
56163 	}
56164 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56165 
56166 	/* Array properties have exotic behavior but they are concrete,
56167 	 * so no special handling here.
56168 	 *
56169 	 * Arguments exotic behavior (E5 Section 10.6, [[GetOwnProperty]]
56170 	 * is only relevant as a post-check implemented below; hence no
56171 	 * check here.
56172 	 */
56173 
56174 	/*
56175 	 *  Not found as concrete or virtual.
56176 	 */
56177 
56178  prop_not_found:
56179 	DUK_DDD(DUK_DDDPRINT("-> not found (virtual, entry part, or array part)"));
56180 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_miss);
56181 	return 0;
56182 
56183 	/*
56184 	 *  Found.
56185 	 *
56186 	 *  Arguments object has exotic post-processing, see E5 Section 10.6,
56187 	 *  description of [[GetOwnProperty]] variant for arguments.
56188 	 */
56189 
56190  prop_found:
56191 	DUK_DDD(DUK_DDDPRINT("-> property found, checking for arguments exotic post-behavior"));
56192 
56193 	/* Notes:
56194 	 *  - Only numbered indices are relevant, so arr_idx fast reject is good
56195 	 *    (this is valid unless there are more than 4**32-1 arguments).
56196 	 *  - Since variable lookup has no side effects, this can be skipped if
56197 	 *    DUK_GETDESC_FLAG_PUSH_VALUE is not set.
56198 	 */
56199 
56200 	if (DUK_UNLIKELY(DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56201 	                 arr_idx != DUK__NO_ARRAY_INDEX &&
56202 	                 (flags & DUK_GETDESC_FLAG_PUSH_VALUE))) {
56203 		duk_propdesc temp_desc;
56204 
56205 		/* Magically bound variable cannot be an accessor.  However,
56206 		 * there may be an accessor property (or a plain property) in
56207 		 * place with magic behavior removed.  This happens e.g. when
56208 		 * a magic property is redefined with defineProperty().
56209 		 * Cannot assert for "not accessor" here.
56210 		 */
56211 
56212 		/* replaces top of stack with new value if necessary */
56213 		DUK_ASSERT((flags & DUK_GETDESC_FLAG_PUSH_VALUE) != 0);
56214 
56215 		/* This can perform a variable lookup but only into a declarative
56216 		 * environment which has no side effects.
56217 		 */
56218 		if (duk__check_arguments_map_for_get(thr, obj, key, &temp_desc)) {
56219 			DUK_DDD(DUK_DDDPRINT("-> arguments exotic behavior overrides result: %!T -> %!T",
56220 			                     (duk_tval *) duk_get_tval(thr, -2),
56221 			                     (duk_tval *) duk_get_tval(thr, -1)));
56222 			/* [... old_result result] -> [... result] */
56223 			duk_remove_m2(thr);
56224 		}
56225 	}
56226 
56227  prop_found_noexotic:
56228 	DUK_STATS_INC(thr->heap, stats_getownpropdesc_hit);
56229 	return 1;
56230 }
56231 
56232 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) {
56233 	DUK_ASSERT(thr != NULL);
56234 	DUK_ASSERT(obj != NULL);
56235 	DUK_ASSERT(key != NULL);
56236 	DUK_ASSERT(out_desc != NULL);
56237 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56238 
56239 	return duk__get_own_propdesc_raw(thr, obj, key, DUK_HSTRING_GET_ARRIDX_SLOW(key), out_desc, flags);
56240 }
56241 
56242 /*
56243  *  ECMAScript compliant [[GetProperty]](P), for internal use only.
56244  *
56245  *  If property is found:
56246  *    - Fills descriptor fields to 'out_desc'
56247  *    - If DUK_GETDESC_FLAG_PUSH_VALUE is set, pushes a value related to the
56248  *      property onto the stack ('undefined' for accessor properties).
56249  *    - Returns non-zero
56250  *
56251  *  If property is not found:
56252  *    - 'out_desc' is left in untouched state (possibly garbage)
56253  *    - Nothing is pushed onto the stack (not even with DUK_GETDESC_FLAG_PUSH_VALUE
56254  *      set)
56255  *    - Returns zero
56256  *
56257  *  May cause arbitrary side effects and invalidate (most) duk_tval
56258  *  pointers.
56259  */
56260 
56261 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) {
56262 	duk_hobject *curr;
56263 	duk_uint32_t arr_idx;
56264 	duk_uint_t sanity;
56265 
56266 	DUK_ASSERT(thr != NULL);
56267 	DUK_ASSERT(thr->heap != NULL);
56268 	DUK_ASSERT(obj != NULL);
56269 	DUK_ASSERT(key != NULL);
56270 	DUK_ASSERT(out_desc != NULL);
56271 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56272 
56273 	DUK_STATS_INC(thr->heap, stats_getpropdesc_count);
56274 
56275 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
56276 
56277 	DUK_DDD(DUK_DDDPRINT("duk__get_propdesc: thr=%p, obj=%p, key=%p, out_desc=%p, flags=%lx, "
56278 	                     "arr_idx=%ld (obj -> %!O, key -> %!O)",
56279 	                     (void *) thr, (void *) obj, (void *) key, (void *) out_desc,
56280 	                     (long) flags, (long) arr_idx,
56281 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
56282 
56283 	curr = obj;
56284 	DUK_ASSERT(curr != NULL);
56285 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56286 	do {
56287 		if (duk__get_own_propdesc_raw(thr, curr, key, arr_idx, out_desc, flags)) {
56288 			/* stack contains value (if requested), 'out_desc' is set */
56289 			DUK_STATS_INC(thr->heap, stats_getpropdesc_hit);
56290 			return 1;
56291 		}
56292 
56293 		/* not found in 'curr', next in prototype chain; impose max depth */
56294 		if (DUK_UNLIKELY(sanity-- == 0)) {
56295 			if (flags & DUK_GETDESC_FLAG_IGNORE_PROTOLOOP) {
56296 				/* treat like property not found */
56297 				break;
56298 			} else {
56299 				DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56300 				DUK_WO_NORETURN(return 0;);
56301 			}
56302 		}
56303 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56304 	} while (curr != NULL);
56305 
56306 	/* out_desc is left untouched (possibly garbage), caller must use return
56307 	 * value to determine whether out_desc can be looked up
56308 	 */
56309 
56310 	DUK_STATS_INC(thr->heap, stats_getpropdesc_miss);
56311 	return 0;
56312 }
56313 
56314 /*
56315  *  Shallow fast path checks for accessing array elements with numeric
56316  *  indices.  The goal is to try to avoid coercing an array index to an
56317  *  (interned) string for the most common lookups, in particular, for
56318  *  standard Array objects.
56319  *
56320  *  Interning is avoided but only for a very narrow set of cases:
56321  *    - Object has array part, index is within array allocation, and
56322  *      value is not unused (= key exists)
56323  *    - Object has no interfering exotic behavior (e.g. arguments or
56324  *      string object exotic behaviors interfere, array exotic
56325  *      behavior does not).
56326  *
56327  *  Current shortcoming: if key does not exist (even if it is within
56328  *  the array allocation range) a slow path lookup with interning is
56329  *  always required.  This can probably be fixed so that there is a
56330  *  quick fast path for non-existent elements as well, at least for
56331  *  standard Array objects.
56332  */
56333 
56334 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56335 DUK_LOCAL duk_tval *duk__getprop_shallow_fastpath_array_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
56336 	duk_tval *tv;
56337 	duk_uint32_t idx;
56338 
56339 	DUK_UNREF(thr);
56340 
56341 	if (!(DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
56342 	     !DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj) &&
56343 	     !DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(obj) &&
56344 	     !DUK_HOBJECT_IS_BUFOBJ(obj) &&
56345 	     !DUK_HOBJECT_IS_PROXY(obj))) {
56346 		/* Must have array part and no conflicting exotic behaviors.
56347 		 * Doesn't need to have array special behavior, e.g. Arguments
56348 		 * object has array part.
56349 		 */
56350 		return NULL;
56351 	}
56352 
56353 	/* Arrays never have other exotic behaviors. */
56354 
56355 	DUK_DDD(DUK_DDDPRINT("fast path attempt (no exotic string/arguments/buffer "
56356 	                     "behavior, object has array part)"));
56357 
56358 #if defined(DUK_USE_FASTINT)
56359 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56360 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56361 	} else
56362 #endif
56363 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56364 		idx = duk__tval_number_to_arr_idx(tv_key);
56365 	} else {
56366 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
56367 		return NULL;
56368 	}
56369 
56370 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56371 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56372 	 * because 0xffffffffUL will never be inside object 'a_size'.
56373 	 */
56374 
56375 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
56376 		DUK_DDD(DUK_DDDPRINT("key is not an array index or outside array part"));
56377 		return NULL;
56378 	}
56379 	DUK_ASSERT(idx != 0xffffffffUL);
56380 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56381 
56382 	/* XXX: for array instances we could take a shortcut here and assume
56383 	 * Array.prototype doesn't contain an array index property.
56384 	 */
56385 
56386 	DUK_DDD(DUK_DDDPRINT("key is a valid array index and inside array part"));
56387 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
56388 	if (!DUK_TVAL_IS_UNUSED(tv)) {
56389 		DUK_DDD(DUK_DDDPRINT("-> fast path successful"));
56390 		return tv;
56391 	}
56392 
56393 	DUK_DDD(DUK_DDDPRINT("fast path attempt failed, fall back to slow path"));
56394 	return NULL;
56395 }
56396 
56397 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) {
56398 	duk_tval *tv;
56399 	duk_harray *a;
56400 	duk_uint32_t idx;
56401 	duk_uint32_t old_len, new_len;
56402 
56403 	if (!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj) &&
56404 	      DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
56405 	      DUK_HOBJECT_HAS_EXTENSIBLE(obj))) {
56406 		return 0;
56407 	}
56408 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures */
56409 
56410 	a = (duk_harray *) obj;
56411 	DUK_ASSERT_HARRAY_VALID(a);
56412 
56413 #if defined(DUK_USE_FASTINT)
56414 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56415 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56416 	} else
56417 #endif
56418 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56419 		idx = duk__tval_number_to_arr_idx(tv_key);
56420 	} else {
56421 		DUK_DDD(DUK_DDDPRINT("key is not a number"));
56422 		return 0;
56423 	}
56424 
56425 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56426 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56427 	 * because 0xffffffffUL will never be inside object 'a_size'.
56428 	 */
56429 
56430 	if (idx >= DUK_HOBJECT_GET_ASIZE(obj)) {  /* for resizing of array part, use slow path */
56431 		return 0;
56432 	}
56433 	DUK_ASSERT(idx != 0xffffffffUL);
56434 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56435 
56436 	old_len = a->length;
56437 
56438 	if (idx >= old_len) {
56439 		DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
56440 		                     "(arr_idx=%ld, old_len=%ld)",
56441 		                     (long) idx, (long) old_len));
56442 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
56443 			/* The correct behavior here is either a silent error
56444 			 * or a TypeError, depending on strictness.  Fall back
56445 			 * to the slow path to handle the situation.
56446 			 */
56447 			return 0;
56448 		}
56449 		new_len = idx + 1;
56450 
56451 		((duk_harray *) obj)->length = new_len;
56452 	}
56453 
56454 	tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, idx);
56455 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects */
56456 
56457 	DUK_DDD(DUK_DDDPRINT("array fast path success for index %ld", (long) idx));
56458 	return 1;
56459 }
56460 #endif  /* DUK_USE_ARRAY_PROP_FASTPATH */
56461 
56462 /*
56463  *  Fast path for bufobj getprop/putprop
56464  */
56465 
56466 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56467 DUK_LOCAL duk_bool_t duk__getprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key) {
56468 	duk_uint32_t idx;
56469 	duk_hbufobj *h_bufobj;
56470 	duk_uint_t byte_off;
56471 	duk_small_uint_t elem_size;
56472 	duk_uint8_t *data;
56473 
56474 	if (!DUK_HOBJECT_IS_BUFOBJ(obj)) {
56475 		return 0;
56476 	}
56477 	h_bufobj = (duk_hbufobj *) obj;
56478 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56479 		return 0;
56480 	}
56481 
56482 #if defined(DUK_USE_FASTINT)
56483 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56484 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56485 	} else
56486 #endif
56487 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56488 		idx = duk__tval_number_to_arr_idx(tv_key);
56489 	} else {
56490 		return 0;
56491 	}
56492 
56493 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56494 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56495 	 * because 0xffffffffUL will never be inside bufobj length.
56496 	 */
56497 
56498 	/* Careful with wrapping (left shifting idx would be unsafe). */
56499 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
56500 		return 0;
56501 	}
56502 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56503 
56504 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56505 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56506 
56507 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56508 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56509 		duk_hbufobj_push_validated_read(thr, h_bufobj, data, elem_size);
56510 	} else {
56511 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (read zero)"));
56512 		duk_push_uint(thr, 0);
56513 	}
56514 
56515 	return 1;
56516 }
56517 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56518 
56519 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56520 DUK_LOCAL duk_bool_t duk__putprop_fastpath_bufobj_tval(duk_hthread *thr, duk_hobject *obj, duk_tval *tv_key, duk_tval *tv_val) {
56521 	duk_uint32_t idx;
56522 	duk_hbufobj *h_bufobj;
56523 	duk_uint_t byte_off;
56524 	duk_small_uint_t elem_size;
56525 	duk_uint8_t *data;
56526 
56527 	if (!(DUK_HOBJECT_IS_BUFOBJ(obj) &&
56528 	      DUK_TVAL_IS_NUMBER(tv_val))) {
56529 		return 0;
56530 	}
56531 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));  /* caller ensures; rom objects are never bufobjs now */
56532 
56533 	h_bufobj = (duk_hbufobj *) obj;
56534 	if (!DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
56535 		return 0;
56536 	}
56537 
56538 #if defined(DUK_USE_FASTINT)
56539 	if (DUK_TVAL_IS_FASTINT(tv_key)) {
56540 		idx = duk__tval_fastint_to_arr_idx(tv_key);
56541 	} else
56542 #endif
56543 	if (DUK_TVAL_IS_DOUBLE(tv_key)) {
56544 		idx = duk__tval_number_to_arr_idx(tv_key);
56545 	} else {
56546 		return 0;
56547 	}
56548 
56549 	/* If index is not valid, idx will be DUK__NO_ARRAY_INDEX which
56550 	 * is 0xffffffffUL.  We don't need to check for that explicitly
56551 	 * because 0xffffffffUL will never be inside bufobj length.
56552 	 */
56553 
56554 	/* Careful with wrapping (left shifting idx would be unsafe). */
56555 	if (idx >= (h_bufobj->length >> h_bufobj->shift)) {
56556 		return 0;
56557 	}
56558 	DUK_ASSERT(idx != DUK__NO_ARRAY_INDEX);
56559 
56560 	byte_off = idx << h_bufobj->shift;  /* no wrap assuming h_bufobj->length is valid */
56561 	elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
56562 
56563 	/* Value is required to be a number in the fast path so there
56564 	 * are no side effects in write coercion.
56565 	 */
56566 	duk_push_tval(thr, tv_val);
56567 	DUK_ASSERT(duk_is_number(thr, -1));
56568 
56569 	if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
56570 		data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
56571 		duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
56572 	} else {
56573 		DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
56574 	}
56575 
56576 	duk_pop_unsafe(thr);
56577 	return 1;
56578 }
56579 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
56580 
56581 /*
56582  *  GETPROP: ECMAScript property read.
56583  */
56584 
56585 DUK_INTERNAL duk_bool_t duk_hobject_getprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
56586 	duk_tval tv_obj_copy;
56587 	duk_tval tv_key_copy;
56588 	duk_hobject *curr = NULL;
56589 	duk_hstring *key = NULL;
56590 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
56591 	duk_propdesc desc;
56592 	duk_uint_t sanity;
56593 
56594 	DUK_DDD(DUK_DDDPRINT("getprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
56595 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
56596 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
56597 
56598 	DUK_ASSERT(thr != NULL);
56599 	DUK_ASSERT(thr->heap != NULL);
56600 	DUK_ASSERT(tv_obj != NULL);
56601 	DUK_ASSERT(tv_key != NULL);
56602 
56603 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
56604 
56605 	DUK_STATS_INC(thr->heap, stats_getprop_all);
56606 
56607 	/*
56608 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
56609 	 *  them being invalidated by a valstack resize.
56610 	 *
56611 	 *  XXX: this is now an overkill for many fast paths.  Rework this
56612 	 *  to be faster (although switching to a valstack discipline might
56613 	 *  be a better solution overall).
56614 	 */
56615 
56616 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
56617 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
56618 	tv_obj = &tv_obj_copy;
56619 	tv_key = &tv_key_copy;
56620 
56621 	/*
56622 	 *  Coercion and fast path processing
56623 	 */
56624 
56625 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
56626 	case DUK_TAG_UNDEFINED:
56627 	case DUK_TAG_NULL: {
56628 		/* Note: unconditional throw */
56629 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
56630 #if defined(DUK_USE_PARANOID_ERRORS)
56631 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
56632 #else
56633 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot read property %s of %s",
56634 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
56635 #endif
56636 		DUK_WO_NORETURN(return 0;);
56637 		break;
56638 	}
56639 
56640 	case DUK_TAG_BOOLEAN: {
56641 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
56642 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
56643 		break;
56644 	}
56645 
56646 	case DUK_TAG_STRING: {
56647 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
56648 		duk_int_t pop_count;
56649 
56650 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
56651 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
56652 			DUK_DDD(DUK_DDDPRINT("base object is a symbol, start lookup from symbol prototype"));
56653 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
56654 			break;
56655 		}
56656 
56657 #if defined(DUK_USE_FASTINT)
56658 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
56659 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
56660 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
56661 			pop_count = 0;
56662 		} else
56663 #endif
56664 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
56665 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
56666 			DUK_DDD(DUK_DDDPRINT("base object string, key is a fast-path number; arr_idx %ld", (long) arr_idx));
56667 			pop_count = 0;
56668 		} else {
56669 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56670 			DUK_ASSERT(key != NULL);
56671 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
56672 			                     "coercion key is %!T, arr_idx %ld",
56673 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56674 			pop_count = 1;
56675 		}
56676 
56677 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
56678 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
56679 			duk_pop_n_unsafe(thr, pop_count);
56680 			duk_push_hstring(thr, h);
56681 			duk_substring(thr, -1, arr_idx, arr_idx + 1);  /* [str] -> [substr] */
56682 
56683 			DUK_STATS_INC(thr->heap, stats_getprop_stringidx);
56684 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is an index inside string length "
56685 			                     "after coercion -> return char)",
56686 			                     (duk_tval *) duk_get_tval(thr, -1)));
56687 			return 1;
56688 		}
56689 
56690 		if (pop_count == 0) {
56691 			/* This is a pretty awkward control flow, but we need to recheck the
56692 			 * key coercion here.
56693 			 */
56694 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56695 			DUK_ASSERT(key != NULL);
56696 			DUK_DDD(DUK_DDDPRINT("base object string, key is a non-fast-path number; after "
56697 			                     "coercion key is %!T, arr_idx %ld",
56698 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56699 		}
56700 
56701 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56702 			duk_pop_unsafe(thr);  /* [key] -> [] */
56703 			duk_push_uint(thr, (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));  /* [] -> [res] */
56704 
56705 			DUK_STATS_INC(thr->heap, stats_getprop_stringlen);
56706 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is string, key is 'length' after coercion -> "
56707 			                     "return string length)",
56708 			                     (duk_tval *) duk_get_tval(thr, -1)));
56709 			return 1;
56710 		}
56711 
56712 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
56713 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
56714 		goto lookup;  /* avoid double coercion */
56715 	}
56716 
56717 	case DUK_TAG_OBJECT: {
56718 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56719 		duk_tval *tmp;
56720 #endif
56721 
56722 		curr = DUK_TVAL_GET_OBJECT(tv_obj);
56723 		DUK_ASSERT(curr != NULL);
56724 
56725 		/* XXX: array .length fast path (important in e.g. loops)? */
56726 
56727 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
56728 		tmp = duk__getprop_shallow_fastpath_array_tval(thr, curr, tv_key);
56729 		if (tmp) {
56730 			duk_push_tval(thr, tmp);
56731 
56732 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is object, key is a number, array part "
56733 			                     "fast path)",
56734 			                     (duk_tval *) duk_get_tval(thr, -1)));
56735 			DUK_STATS_INC(thr->heap, stats_getprop_arrayidx);
56736 			return 1;
56737 		}
56738 #endif
56739 
56740 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
56741 		if (duk__getprop_fastpath_bufobj_tval(thr, curr, tv_key) != 0) {
56742 			/* Read value pushed on stack. */
56743 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is bufobj, key is a number, bufobj "
56744 			                     "fast path)",
56745 			                     (duk_tval *) duk_get_tval(thr, -1)));
56746 			DUK_STATS_INC(thr->heap, stats_getprop_bufobjidx);
56747 			return 1;
56748 		}
56749 #endif
56750 
56751 #if defined(DUK_USE_ES6_PROXY)
56752 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(curr))) {
56753 			duk_hobject *h_target;
56754 
56755 			if (duk__proxy_check_prop(thr, curr, DUK_STRIDX_GET, tv_key, &h_target)) {
56756 				/* -> [ ... trap handler ] */
56757 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'get' for key %!T", (duk_tval *) tv_key));
56758 				DUK_STATS_INC(thr->heap, stats_getprop_proxy);
56759 				duk_push_hobject(thr, h_target);  /* target */
56760 				duk_push_tval(thr, tv_key);       /* P */
56761 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
56762 				duk_call_method(thr, 3 /*nargs*/);
56763 
56764 				/* Target object must be checked for a conflicting
56765 				 * non-configurable property.
56766 				 */
56767 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56768 				DUK_ASSERT(key != NULL);
56769 
56770 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56771 					duk_tval *tv_hook = duk_require_tval(thr, -3);  /* value from hook */
56772 					duk_tval *tv_targ = duk_require_tval(thr, -1);  /* value from target */
56773 					duk_bool_t datadesc_reject;
56774 					duk_bool_t accdesc_reject;
56775 
56776 					DUK_DDD(DUK_DDDPRINT("proxy 'get': target has matching property %!O, check for "
56777 					                     "conflicting property; tv_hook=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
56778 					                     "desc.get=%p, desc.set=%p",
56779 					                     (duk_heaphdr *) key, (duk_tval *) tv_hook, (duk_tval *) tv_targ,
56780 					                     (unsigned long) desc.flags,
56781 					                     (void *) desc.get, (void *) desc.set));
56782 
56783 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
56784 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
56785 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
56786 					                  !duk_js_samevalue(tv_hook, tv_targ);
56787 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
56788 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
56789 					                 (desc.get == NULL) &&
56790 					                 !DUK_TVAL_IS_UNDEFINED(tv_hook);
56791 					if (datadesc_reject || accdesc_reject) {
56792 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
56793 						DUK_WO_NORETURN(return 0;);
56794 					}
56795 
56796 					duk_pop_2_unsafe(thr);
56797 				} else {
56798 					duk_pop_unsafe(thr);
56799 				}
56800 				return 1;  /* return value */
56801 			}
56802 
56803 			curr = h_target;  /* resume lookup from target */
56804 			DUK_TVAL_SET_OBJECT(tv_obj, curr);
56805 		}
56806 #endif  /* DUK_USE_ES6_PROXY */
56807 
56808 		if (DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(curr)) {
56809 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56810 			DUK_ASSERT(key != NULL);
56811 
56812 			DUK_STATS_INC(thr->heap, stats_getprop_arguments);
56813 			if (duk__check_arguments_map_for_get(thr, curr, key, &desc)) {
56814 				DUK_DDD(DUK_DDDPRINT("-> %!T (base is object with arguments exotic behavior, "
56815 				                     "key matches magically bound property -> skip standard "
56816 				                     "Get with replacement value)",
56817 				                     (duk_tval *) duk_get_tval(thr, -1)));
56818 
56819 				/* no need for 'caller' post-check, because 'key' must be an array index */
56820 
56821 				duk_remove_m2(thr);  /* [key result] -> [result] */
56822 				return 1;
56823 			}
56824 
56825 			goto lookup;  /* avoid double coercion */
56826 		}
56827 		break;
56828 	}
56829 
56830 	/* Buffer has virtual properties similar to string, but indexed values
56831 	 * are numbers, not 1-byte buffers/strings which would perform badly.
56832 	 */
56833 	case DUK_TAG_BUFFER: {
56834 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
56835 		duk_int_t pop_count;
56836 
56837 		/*
56838 		 *  Because buffer values are often looped over, a number fast path
56839 		 *  is important.
56840 		 */
56841 
56842 #if defined(DUK_USE_FASTINT)
56843 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
56844 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
56845 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
56846 			pop_count = 0;
56847 		}
56848 		else
56849 #endif
56850 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
56851 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
56852 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
56853 			pop_count = 0;
56854 		} else {
56855 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56856 			DUK_ASSERT(key != NULL);
56857 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
56858 			                     "coercion key is %!T, arr_idx %ld",
56859 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56860 			pop_count = 1;
56861 		}
56862 
56863 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
56864 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
56865 			duk_pop_n_unsafe(thr, pop_count);
56866 			duk_push_uint(thr, ((duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h))[arr_idx]);
56867 			DUK_STATS_INC(thr->heap, stats_getprop_bufferidx);
56868 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is an index inside buffer length "
56869 			                     "after coercion -> return byte as number)",
56870 			                     (duk_tval *) duk_get_tval(thr, -1)));
56871 			return 1;
56872 		}
56873 
56874 		if (pop_count == 0) {
56875 			/* This is a pretty awkward control flow, but we need to recheck the
56876 			 * key coercion here.
56877 			 */
56878 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56879 			DUK_ASSERT(key != NULL);
56880 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
56881 			                     "coercion key is %!T, arr_idx %ld",
56882 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
56883 		}
56884 
56885 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
56886 			duk_pop_unsafe(thr);  /* [key] -> [] */
56887 			duk_push_uint(thr, (duk_uint_t) DUK_HBUFFER_GET_SIZE(h));  /* [] -> [res] */
56888 			DUK_STATS_INC(thr->heap, stats_getprop_bufferlen);
56889 
56890 			DUK_DDD(DUK_DDDPRINT("-> %!T (base is buffer, key is 'length' "
56891 			                     "after coercion -> return buffer length)",
56892 			                     (duk_tval *) duk_get_tval(thr, -1)));
56893 			return 1;
56894 		}
56895 
56896 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
56897 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
56898 		goto lookup;  /* avoid double coercion */
56899 	}
56900 
56901 	case DUK_TAG_POINTER: {
56902 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
56903 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
56904 		break;
56905 	}
56906 
56907 	case DUK_TAG_LIGHTFUNC: {
56908 		/* Lightfuncs inherit getter .name and .length from %NativeFunctionPrototype%. */
56909 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
56910 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
56911 		break;
56912 	}
56913 
56914 #if defined(DUK_USE_FASTINT)
56915 	case DUK_TAG_FASTINT:
56916 #endif
56917 	default: {
56918 		/* number */
56919 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
56920 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_obj));
56921 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
56922 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
56923 		break;
56924 	}
56925 	}
56926 
56927 	/* key coercion (unless already coerced above) */
56928 	DUK_ASSERT(key == NULL);
56929 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
56930 	DUK_ASSERT(key != NULL);
56931 	/*
56932 	 *  Property lookup
56933 	 */
56934 
56935  lookup:
56936 	/* [key] (coerced) */
56937 	DUK_ASSERT(curr != NULL);
56938 	DUK_ASSERT(key != NULL);
56939 
56940 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
56941 	do {
56942 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
56943 			goto next_in_chain;
56944 		}
56945 
56946 		if (desc.get != NULL) {
56947 			/* accessor with defined getter */
56948 			DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) != 0);
56949 
56950 			duk_pop_unsafe(thr);              /* [key undefined] -> [key] */
56951 			duk_push_hobject(thr, desc.get);
56952 			duk_push_tval(thr, tv_obj);       /* note: original, uncoerced base */
56953 #if defined(DUK_USE_NONSTD_GETTER_KEY_ARGUMENT)
56954 			duk_dup_m3(thr);
56955 			duk_call_method(thr, 1);          /* [key getter this key] -> [key retval] */
56956 #else
56957 			duk_call_method(thr, 0);          /* [key getter this] -> [key retval] */
56958 #endif
56959 		} else {
56960 			/* [key value] or [key undefined] */
56961 
56962 			/* data property or accessor without getter */
56963 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
56964 			           (desc.get == NULL));
56965 
56966 			/* if accessor without getter, return value is undefined */
56967 			DUK_ASSERT(((desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) == 0) ||
56968 			           duk_is_undefined(thr, -1));
56969 
56970 			/* Note: for an accessor without getter, falling through to
56971 			 * check for "caller" exotic behavior is unnecessary as
56972 			 * "undefined" will never activate the behavior.  But it does
56973 			 * no harm, so we'll do it anyway.
56974 			 */
56975 		}
56976 
56977 		goto found;  /* [key result] */
56978 
56979 	 next_in_chain:
56980 		/* XXX: option to pretend property doesn't exist if sanity limit is
56981 		 * hit might be useful.
56982 		 */
56983 		if (DUK_UNLIKELY(sanity-- == 0)) {
56984 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
56985 			DUK_WO_NORETURN(return 0;);
56986 		}
56987 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
56988 	} while (curr != NULL);
56989 
56990 	/*
56991 	 *  Not found
56992 	 */
56993 
56994 	duk_to_undefined(thr, -1);  /* [key] -> [undefined] (default value) */
56995 
56996 	DUK_DDD(DUK_DDDPRINT("-> %!T (not found)", (duk_tval *) duk_get_tval(thr, -1)));
56997 	return 0;
56998 
56999 	/*
57000 	 *  Found; post-processing (Function and arguments objects)
57001 	 */
57002 
57003  found:
57004 	/* [key result] */
57005 
57006 #if !defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
57007 	/* Special behavior for 'caller' property of (non-bound) function objects
57008 	 * and non-strict Arguments objects: if 'caller' -value- (!) is a strict
57009 	 * mode function, throw a TypeError (E5 Sections 15.3.5.4, 10.6).
57010 	 * Quite interestingly, a non-strict function with no formal arguments
57011 	 * will get an arguments object -without- special 'caller' behavior!
57012 	 *
57013 	 * The E5.1 spec is a bit ambiguous if this special behavior applies when
57014 	 * a bound function is the base value (not the 'caller' value): Section
57015 	 * 15.3.4.5 (describing bind()) states that [[Get]] for bound functions
57016 	 * matches that of Section 15.3.5.4 ([[Get]] for Function instances).
57017 	 * However, Section 13.3.5.4 has "NOTE: Function objects created using
57018 	 * Function.prototype.bind use the default [[Get]] internal method."
57019 	 * The current implementation assumes this means that bound functions
57020 	 * should not have the special [[Get]] behavior.
57021 	 *
57022 	 * The E5.1 spec is also a bit unclear if the TypeError throwing is
57023 	 * applied if the 'caller' value is a strict bound function.  The
57024 	 * current implementation will throw even for both strict non-bound
57025 	 * and strict bound functions.
57026 	 *
57027 	 * See test-dev-strict-func-as-caller-prop-value.js for quite extensive
57028 	 * tests.
57029 	 *
57030 	 * This exotic behavior is disabled when the non-standard 'caller' property
57031 	 * is enabled, as it conflicts with the free use of 'caller'.
57032 	 */
57033 	if (key == DUK_HTHREAD_STRING_CALLER(thr) &&
57034 	    DUK_TVAL_IS_OBJECT(tv_obj)) {
57035 		duk_hobject *orig = DUK_TVAL_GET_OBJECT(tv_obj);
57036 		DUK_ASSERT(orig != NULL);
57037 
57038 		if (DUK_HOBJECT_IS_NONBOUND_FUNCTION(orig) ||
57039 		    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
57040 			duk_hobject *h;
57041 
57042 			/* XXX: The TypeError is currently not applied to bound
57043 			 * functions because the 'strict' flag is not copied by
57044 			 * bind().  This may or may not be correct, the specification
57045 			 * only refers to the value being a "strict mode Function
57046 			 * object" which is ambiguous.
57047 			 */
57048 			DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(orig));
57049 
57050 			h = duk_get_hobject(thr, -1);  /* NULL if not an object */
57051 			if (h &&
57052 			    DUK_HOBJECT_IS_FUNCTION(h) &&
57053 			    DUK_HOBJECT_HAS_STRICT(h)) {
57054 				/* XXX: sufficient to check 'strict', assert for 'is function' */
57055 				DUK_ERROR_TYPE(thr, DUK_STR_STRICT_CALLER_READ);
57056 				DUK_WO_NORETURN(return 0;);
57057 			}
57058 		}
57059 	}
57060 #endif   /* !DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
57061 
57062 	duk_remove_m2(thr);  /* [key result] -> [result] */
57063 
57064 	DUK_DDD(DUK_DDDPRINT("-> %!T (found)", (duk_tval *) duk_get_tval(thr, -1)));
57065 	return 1;
57066 }
57067 
57068 /*
57069  *  HASPROP: ECMAScript property existence check ("in" operator).
57070  *
57071  *  Interestingly, the 'in' operator does not do any coercion of
57072  *  the target object.
57073  */
57074 
57075 DUK_INTERNAL duk_bool_t duk_hobject_hasprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key) {
57076 	duk_tval tv_key_copy;
57077 	duk_hobject *obj;
57078 	duk_hstring *key;
57079 	duk_uint32_t arr_idx;
57080 	duk_bool_t rc;
57081 	duk_propdesc desc;
57082 
57083 	DUK_DDD(DUK_DDDPRINT("hasprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
57084 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
57085 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
57086 
57087 	DUK_ASSERT(thr != NULL);
57088 	DUK_ASSERT(thr->heap != NULL);
57089 	DUK_ASSERT(tv_obj != NULL);
57090 	DUK_ASSERT(tv_key != NULL);
57091 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57092 
57093 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57094 	tv_key = &tv_key_copy;
57095 
57096 	/*
57097 	 *  The 'in' operator requires an object as its right hand side,
57098 	 *  throwing a TypeError unconditionally if this is not the case.
57099 	 *
57100 	 *  However, lightfuncs need to behave like fully fledged objects
57101 	 *  here to be maximally transparent, so we need to handle them
57102 	 *  here.  Same goes for plain buffers which behave like ArrayBuffers.
57103 	 */
57104 
57105 	/* XXX: Refactor key coercion so that it's only called once.  It can't
57106 	 * be trivially lifted here because the object must be type checked
57107 	 * first.
57108 	 */
57109 
57110 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
57111 		obj = DUK_TVAL_GET_OBJECT(tv_obj);
57112 		DUK_ASSERT(obj != NULL);
57113 
57114 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57115 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
57116 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57117 		if (duk__key_is_plain_buf_ownprop(thr, DUK_TVAL_GET_BUFFER(tv_obj), key, arr_idx)) {
57118 			rc = 1;
57119 			goto pop_and_return;
57120 		}
57121 		obj = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57122 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
57123 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57124 
57125 		/* If not found, resume existence check from %NativeFunctionPrototype%.
57126 		 * We can just substitute the value in this case; nothing will
57127 		 * need the original base value (as would be the case with e.g.
57128 		 * setters/getters.
57129 		 */
57130 		obj = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57131 	} else {
57132 		/* Note: unconditional throw */
57133 		DUK_DDD(DUK_DDDPRINT("base object is not an object -> reject"));
57134 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57135 		DUK_WO_NORETURN(return 0;);
57136 	}
57137 
57138 	/* XXX: fast path for arrays? */
57139 
57140 	DUK_ASSERT(key != NULL);
57141 	DUK_ASSERT(obj != NULL);
57142 	DUK_UNREF(arr_idx);
57143 
57144 #if defined(DUK_USE_ES6_PROXY)
57145 	if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
57146 		duk_hobject *h_target;
57147 		duk_bool_t tmp_bool;
57148 
57149 		/* XXX: the key in 'key in obj' is string coerced before we're called
57150 		 * (which is the required behavior in E5/E5.1/E6) so the key is a string
57151 		 * here already.
57152 		 */
57153 
57154 		if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_HAS, tv_key, &h_target)) {
57155 			/* [ ... key trap handler ] */
57156 			DUK_DDD(DUK_DDDPRINT("-> proxy object 'has' for key %!T", (duk_tval *) tv_key));
57157 			duk_push_hobject(thr, h_target);  /* target */
57158 			duk_push_tval(thr, tv_key);       /* P */
57159 			duk_call_method(thr, 2 /*nargs*/);
57160 			tmp_bool = duk_to_boolean_top_pop(thr);
57161 			if (!tmp_bool) {
57162 				/* Target object must be checked for a conflicting
57163 				 * non-configurable property.
57164 				 */
57165 
57166 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
57167 					DUK_DDD(DUK_DDDPRINT("proxy 'has': target has matching property %!O, check for "
57168 					                     "conflicting property; desc.flags=0x%08lx, "
57169 					                     "desc.get=%p, desc.set=%p",
57170 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
57171 					                     (void *) desc.get, (void *) desc.set));
57172 					/* XXX: Extensibility check for target uses IsExtensible().  If we
57173 					 * implemented the isExtensible trap and didn't reject proxies as
57174 					 * proxy targets, it should be respected here.
57175 					 */
57176 					if (!((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&  /* property is configurable and */
57177 					      DUK_HOBJECT_HAS_EXTENSIBLE(h_target))) {          /* ... target is extensible */
57178 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57179 						DUK_WO_NORETURN(return 0;);
57180 					}
57181 				}
57182 			}
57183 
57184 			duk_pop_unsafe(thr);  /* [ key ] -> [] */
57185 			return tmp_bool;
57186 		}
57187 
57188 		obj = h_target;  /* resume check from proxy target */
57189 	}
57190 #endif  /* DUK_USE_ES6_PROXY */
57191 
57192 	/* XXX: inline into a prototype walking loop? */
57193 
57194 	rc = duk__get_propdesc(thr, obj, key, &desc, 0 /*flags*/);  /* don't push value */
57195 	/* fall through */
57196 
57197  pop_and_return:
57198 	duk_pop_unsafe(thr);  /* [ key ] -> [] */
57199 	return rc;
57200 }
57201 
57202 /*
57203  *  HASPROP variant used internally.
57204  *
57205  *  This primitive must never throw an error, callers rely on this.
57206  *  In particular, don't throw an error for prototype loops; instead,
57207  *  pretend like the property doesn't exist if a prototype sanity limit
57208  *  is reached.
57209  *
57210  *  Does not implement proxy behavior: if applied to a proxy object,
57211  *  returns key existence on the proxy object itself.
57212  */
57213 
57214 DUK_INTERNAL duk_bool_t duk_hobject_hasprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key) {
57215 	duk_propdesc dummy;
57216 
57217 	DUK_ASSERT(thr != NULL);
57218 	DUK_ASSERT(thr->heap != NULL);
57219 	DUK_ASSERT(obj != NULL);
57220 	DUK_ASSERT(key != NULL);
57221 
57222 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57223 
57224 	return duk__get_propdesc(thr, obj, key, &dummy, DUK_GETDESC_FLAG_IGNORE_PROTOLOOP);  /* don't push value */
57225 }
57226 
57227 /*
57228  *  Helper: handle Array object 'length' write which automatically
57229  *  deletes properties, see E5 Section 15.4.5.1, step 3.  This is
57230  *  quite tricky to get right.
57231  *
57232  *  Used by duk_hobject_putprop().
57233  */
57234 
57235 /* Coerce a new .length candidate to a number and check that it's a valid
57236  * .length.
57237  */
57238 DUK_LOCAL duk_uint32_t duk__to_new_array_length_checked(duk_hthread *thr, duk_tval *tv) {
57239 	duk_uint32_t res;
57240 	duk_double_t d;
57241 
57242 #if !defined(DUK_USE_PREFER_SIZE)
57243 #if defined(DUK_USE_FASTINT)
57244 	/* When fastints are enabled, the most interesting case is assigning
57245 	 * a fastint to .length (e.g. arr.length = 0).
57246 	 */
57247 	if (DUK_TVAL_IS_FASTINT(tv)) {
57248 		/* Very common case. */
57249 		duk_int64_t fi;
57250 		fi = DUK_TVAL_GET_FASTINT(tv);
57251 		if (fi < 0 || fi > DUK_I64_CONSTANT(0xffffffff)) {
57252 			goto fail_range;
57253 		}
57254 		return (duk_uint32_t) fi;
57255 	}
57256 #else  /* DUK_USE_FASTINT */
57257 	/* When fastints are not enabled, the most interesting case is any
57258 	 * number.
57259 	 */
57260 	if (DUK_TVAL_IS_DOUBLE(tv)) {
57261 		d = DUK_TVAL_GET_NUMBER(tv);
57262 	}
57263 #endif  /* DUK_USE_FASTINT */
57264 	else
57265 #endif  /* !DUK_USE_PREFER_SIZE */
57266 	{
57267 		/* In all other cases, and when doing a size optimized build,
57268 		 * fall back to the comprehensive handler.
57269 		 */
57270 		d = duk_js_tonumber(thr, tv);
57271 	}
57272 
57273 	/* Refuse to update an Array's 'length' to a value outside the
57274 	 * 32-bit range.  Negative zero is accepted as zero.
57275 	 */
57276 	res = duk_double_to_uint32_t(d);
57277 	if ((duk_double_t) res != d) {
57278 		goto fail_range;
57279 	}
57280 
57281 	return res;
57282 
57283  fail_range:
57284 	DUK_ERROR_RANGE(thr, DUK_STR_INVALID_ARRAY_LENGTH);
57285 	DUK_WO_NORETURN(return 0;);
57286 }
57287 
57288 /* Delete elements required by a smaller length, taking into account
57289  * potentially non-configurable elements.  Returns non-zero if all
57290  * elements could be deleted, and zero if all or some elements could
57291  * not be deleted.  Also writes final "target length" to 'out_result_len'.
57292  * This is the length value that should go into the 'length' property
57293  * (must be set by the caller).  Never throws an error.
57294  */
57295 DUK_LOCAL
57296 duk_bool_t duk__handle_put_array_length_smaller(duk_hthread *thr,
57297                                                 duk_hobject *obj,
57298                                                 duk_uint32_t old_len,
57299                                                 duk_uint32_t new_len,
57300                                                 duk_bool_t force_flag,
57301                                                 duk_uint32_t *out_result_len) {
57302 	duk_uint32_t target_len;
57303 	duk_uint_fast32_t i;
57304 	duk_uint32_t arr_idx;
57305 	duk_hstring *key;
57306 	duk_tval *tv;
57307 	duk_bool_t rc;
57308 
57309 	DUK_DDD(DUK_DDDPRINT("new array length smaller than old (%ld -> %ld), "
57310 	                     "probably need to remove elements",
57311 	                     (long) old_len, (long) new_len));
57312 
57313 	/*
57314 	 *  New length is smaller than old length, need to delete properties above
57315 	 *  the new length.
57316 	 *
57317 	 *  If array part exists, this is straightforward: array entries cannot
57318 	 *  be non-configurable so this is guaranteed to work.
57319 	 *
57320 	 *  If array part does not exist, array-indexed values are scattered
57321 	 *  in the entry part, and some may not be configurable (preventing length
57322 	 *  from becoming lower than their index + 1).  To handle the algorithm
57323 	 *  in E5 Section 15.4.5.1, step l correctly, we scan the entire property
57324 	 *  set twice.
57325 	 */
57326 
57327 	DUK_ASSERT(thr != NULL);
57328 	DUK_ASSERT(obj != NULL);
57329 	DUK_ASSERT(new_len < old_len);
57330 	DUK_ASSERT(out_result_len != NULL);
57331 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57332 
57333 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
57334 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
57335 
57336 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
57337 		/*
57338 		 *  All defined array-indexed properties are in the array part
57339 		 *  (we assume the array part is comprehensive), and all array
57340 		 *  entries are writable, configurable, and enumerable.  Thus,
57341 		 *  nothing can prevent array entries from being deleted.
57342 		 */
57343 
57344 		DUK_DDD(DUK_DDDPRINT("have array part, easy case"));
57345 
57346 		if (old_len < DUK_HOBJECT_GET_ASIZE(obj)) {
57347 			/* XXX: assertion that entries >= old_len are already unused */
57348 			i = old_len;
57349 		} else {
57350 			i = DUK_HOBJECT_GET_ASIZE(obj);
57351 		}
57352 		DUK_ASSERT(i <= DUK_HOBJECT_GET_ASIZE(obj));
57353 
57354 		while (i > new_len) {
57355 			i--;
57356 			tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
57357 			DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
57358 		}
57359 
57360 		*out_result_len = new_len;
57361 		return 1;
57362 	} else {
57363 		/*
57364 		 *  Entries part is a bit more complex.
57365 		 */
57366 
57367 		/* Stage 1: find highest preventing non-configurable entry (if any).
57368 		 * When forcing, ignore non-configurability.
57369 		 */
57370 
57371 		DUK_DDD(DUK_DDDPRINT("no array part, slow case"));
57372 
57373 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 1: find target_len "
57374 		                     "(highest preventing non-configurable entry (if any))"));
57375 
57376 		target_len = new_len;
57377 		if (force_flag) {
57378 			DUK_DDD(DUK_DDDPRINT("array length write, no array part; force flag -> skip stage 1"));
57379 			goto skip_stage1;
57380 		}
57381 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57382 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57383 			if (!key) {
57384 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
57385 				continue;
57386 			}
57387 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
57388 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
57389 				continue;
57390 			}
57391 
57392 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
57393 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
57394 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
57395 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
57396 
57397 			if (arr_idx < new_len) {
57398 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below new_len",
57399 				                     (long) i, (long) arr_idx));
57400 				continue;
57401 			}
57402 			if (DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i)) {
57403 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is a relevant array index %ld, but configurable",
57404 				                     (long) i, (long) arr_idx));
57405 				continue;
57406 			}
57407 
57408 			/* relevant array index is non-configurable, blocks write */
57409 			if (arr_idx >= target_len) {
57410 				DUK_DDD(DUK_DDDPRINT("entry at index %ld has arr_idx %ld, is not configurable, "
57411 				                     "update target_len %ld -> %ld",
57412 				                     (long) i, (long) arr_idx, (long) target_len,
57413 				                     (long) (arr_idx + 1)));
57414 				target_len = arr_idx + 1;
57415 			}
57416 		}
57417 	 skip_stage1:
57418 
57419 		/* stage 2: delete configurable entries above target length */
57420 
57421 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld, target_len=%ld",
57422 		                     (long) old_len, (long) new_len, (long) target_len));
57423 
57424 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 2: remove "
57425 		                     "entries >= target_len"));
57426 
57427 		for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
57428 			key = DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i);
57429 			if (!key) {
57430 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: null key", (long) i));
57431 				continue;
57432 			}
57433 			if (!DUK_HSTRING_HAS_ARRIDX(key)) {
57434 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key not an array index", (long) i));
57435 				continue;
57436 			}
57437 
57438 			DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(key));  /* XXX: macro checks for array index flag, which is unnecessary here */
57439 			arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
57440 			DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);
57441 			DUK_ASSERT(arr_idx < old_len);  /* consistency requires this */
57442 
57443 			if (arr_idx < target_len) {
57444 				DUK_DDD(DUK_DDDPRINT("skip entry index %ld: key is array index %ld, below target_len",
57445 				                     (long) i, (long) arr_idx));
57446 				continue;
57447 			}
57448 			DUK_ASSERT(force_flag || DUK_HOBJECT_E_SLOT_IS_CONFIGURABLE(thr->heap, obj, i));  /* stage 1 guarantees */
57449 
57450 			DUK_DDD(DUK_DDDPRINT("delete entry index %ld: key is array index %ld",
57451 			                     (long) i, (long) arr_idx));
57452 
57453 			/*
57454 			 *  Slow delete, but we don't care as we're already in a very slow path.
57455 			 *  The delete always succeeds: key has no exotic behavior, property
57456 			 *  is configurable, and no resize occurs.
57457 			 */
57458 			rc = duk_hobject_delprop_raw(thr, obj, key, force_flag ? DUK_DELPROP_FLAG_FORCE : 0);
57459 			DUK_UNREF(rc);
57460 			DUK_ASSERT(rc != 0);
57461 		}
57462 
57463 		/* stage 3: update length (done by caller), decide return code */
57464 
57465 		DUK_DDD(DUK_DDDPRINT("array length write, no array part, stage 3: update length (done by caller)"));
57466 
57467 		*out_result_len = target_len;
57468 
57469 		if (target_len == new_len) {
57470 			DUK_DDD(DUK_DDDPRINT("target_len matches new_len, return success"));
57471 			return 1;
57472 		}
57473 		DUK_DDD(DUK_DDDPRINT("target_len does not match new_len (some entry prevented "
57474 		                     "full length adjustment), return error"));
57475 		return 0;
57476 	}
57477 
57478 	DUK_UNREACHABLE();
57479 }
57480 
57481 /* XXX: is valstack top best place for argument? */
57482 DUK_LOCAL duk_bool_t duk__handle_put_array_length(duk_hthread *thr, duk_hobject *obj) {
57483 	duk_harray *a;
57484 	duk_uint32_t old_len;
57485 	duk_uint32_t new_len;
57486 	duk_uint32_t result_len;
57487 	duk_bool_t rc;
57488 
57489 	DUK_DDD(DUK_DDDPRINT("handling a put operation to array 'length' exotic property, "
57490 	                     "new val: %!T",
57491 	                     (duk_tval *) duk_get_tval(thr, -1)));
57492 
57493 	DUK_ASSERT(thr != NULL);
57494 	DUK_ASSERT(obj != NULL);
57495 
57496 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57497 
57498 	DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));
57499 	DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(obj));
57500 	a = (duk_harray *) obj;
57501 	DUK_ASSERT_HARRAY_VALID(a);
57502 
57503 	DUK_ASSERT(duk_is_valid_index(thr, -1));
57504 
57505 	/*
57506 	 *  Get old and new length
57507 	 */
57508 
57509 	old_len = a->length;
57510 	new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
57511 	DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) old_len, (long) new_len));
57512 
57513 	/*
57514 	 *  Writability check
57515 	 */
57516 
57517 	if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
57518 		DUK_DDD(DUK_DDDPRINT("length is not writable, fail"));
57519 		return 0;
57520 	}
57521 
57522 	/*
57523 	 *  New length not lower than old length => no changes needed
57524 	 *  (not even array allocation).
57525 	 */
57526 
57527 	if (new_len >= old_len) {
57528 		DUK_DDD(DUK_DDDPRINT("new length is same or higher than old length, just update length, no deletions"));
57529 		a->length = new_len;
57530 		return 1;
57531 	}
57532 
57533 	DUK_DDD(DUK_DDDPRINT("new length is lower than old length, probably must delete entries"));
57534 
57535 	/*
57536 	 *  New length lower than old length => delete elements, then
57537 	 *  update length.
57538 	 *
57539 	 *  Note: even though a bunch of elements have been deleted, the 'desc' is
57540 	 *  still valid as properties haven't been resized (and entries compacted).
57541 	 */
57542 
57543 	rc = duk__handle_put_array_length_smaller(thr, obj, old_len, new_len, 0 /*force_flag*/, &result_len);
57544 	DUK_ASSERT(result_len >= new_len && result_len <= old_len);
57545 
57546 	a->length = result_len;
57547 
57548 	/* XXX: shrink array allocation or entries compaction here? */
57549 
57550 	return rc;
57551 }
57552 
57553 /*
57554  *  PUTPROP: ECMAScript property write.
57555  *
57556  *  Unlike ECMAScript primitive which returns nothing, returns 1 to indicate
57557  *  success and 0 to indicate failure (assuming throw is not set).
57558  *
57559  *  This is an extremely tricky function.  Some examples:
57560  *
57561  *    * Currently a decref may trigger a GC, which may compact an object's
57562  *      property allocation.  Consequently, any entry indices (e_idx) will
57563  *      be potentially invalidated by a decref.
57564  *
57565  *    * Exotic behaviors (strings, arrays, arguments object) require,
57566  *      among other things:
57567  *
57568  *      - Preprocessing before and postprocessing after an actual property
57569  *        write.  For example, array index write requires pre-checking the
57570  *        array 'length' property for access control, and may require an
57571  *        array 'length' update after the actual write has succeeded (but
57572  *        not if it fails).
57573  *
57574  *      - Deletion of multiple entries, as a result of array 'length' write.
57575  *
57576  *    * Input values are taken as pointers which may point to the valstack.
57577  *      If valstack is resized because of the put (this may happen at least
57578  *      when the array part is abandoned), the pointers can be invalidated.
57579  *      (We currently make a copy of all of the input values to avoid issues.)
57580  */
57581 
57582 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) {
57583 	duk_tval tv_obj_copy;
57584 	duk_tval tv_key_copy;
57585 	duk_tval tv_val_copy;
57586 	duk_hobject *orig = NULL;  /* NULL if tv_obj is primitive */
57587 	duk_hobject *curr;
57588 	duk_hstring *key = NULL;
57589 	duk_propdesc desc;
57590 	duk_tval *tv;
57591 	duk_uint32_t arr_idx;
57592 	duk_bool_t rc;
57593 	duk_int_t e_idx;
57594 	duk_uint_t sanity;
57595 	duk_uint32_t new_array_length = 0;  /* 0 = no update */
57596 
57597 	DUK_DDD(DUK_DDDPRINT("putprop: thr=%p, obj=%p, key=%p, val=%p, throw=%ld "
57598 	                     "(obj -> %!T, key -> %!T, val -> %!T)",
57599 	                     (void *) thr, (void *) tv_obj, (void *) tv_key, (void *) tv_val,
57600 	                     (long) throw_flag, (duk_tval *) tv_obj, (duk_tval *) tv_key, (duk_tval *) tv_val));
57601 
57602 	DUK_ASSERT(thr != NULL);
57603 	DUK_ASSERT(thr->heap != NULL);
57604 	DUK_ASSERT(tv_obj != NULL);
57605 	DUK_ASSERT(tv_key != NULL);
57606 	DUK_ASSERT(tv_val != NULL);
57607 
57608 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
57609 
57610 	DUK_STATS_INC(thr->heap, stats_putprop_all);
57611 
57612 	/*
57613 	 *  Make a copy of tv_obj, tv_key, and tv_val to avoid any issues of
57614 	 *  them being invalidated by a valstack resize.
57615 	 *
57616 	 *  XXX: this is an overkill for some paths, so optimize this later
57617 	 *  (or maybe switch to a stack arguments model entirely).
57618 	 */
57619 
57620 	DUK_TVAL_SET_TVAL(&tv_obj_copy, tv_obj);
57621 	DUK_TVAL_SET_TVAL(&tv_key_copy, tv_key);
57622 	DUK_TVAL_SET_TVAL(&tv_val_copy, tv_val);
57623 	tv_obj = &tv_obj_copy;
57624 	tv_key = &tv_key_copy;
57625 	tv_val = &tv_val_copy;
57626 
57627 	/*
57628 	 *  Coercion and fast path processing.
57629 	 */
57630 
57631 	switch (DUK_TVAL_GET_TAG(tv_obj)) {
57632 	case DUK_TAG_UNDEFINED:
57633 	case DUK_TAG_NULL: {
57634 		/* Note: unconditional throw */
57635 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject (object=%!iT)",
57636 		                     (duk_tval *) tv_obj));
57637 #if defined(DUK_USE_PARANOID_ERRORS)
57638 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
57639 #else
57640 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
57641 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
57642 #endif
57643 		DUK_WO_NORETURN(return 0;);
57644 		break;
57645 	}
57646 
57647 	case DUK_TAG_BOOLEAN: {
57648 		DUK_DDD(DUK_DDDPRINT("base object is a boolean, start lookup from boolean prototype"));
57649 		curr = thr->builtins[DUK_BIDX_BOOLEAN_PROTOTYPE];
57650 		break;
57651 	}
57652 
57653 	case DUK_TAG_STRING: {
57654 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
57655 
57656 		/*
57657 		 *  Note: currently no fast path for array index writes.
57658 		 *  They won't be possible anyway as strings are immutable.
57659 		 */
57660 
57661 		DUK_ASSERT(key == NULL);
57662 		arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57663 		DUK_ASSERT(key != NULL);
57664 
57665 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
57666 			/* Symbols (ES2015 or hidden) don't have virtual properties. */
57667 			curr = thr->builtins[DUK_BIDX_SYMBOL_PROTOTYPE];
57668 			goto lookup;
57669 		}
57670 
57671 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57672 			goto fail_not_writable;
57673 		}
57674 
57675 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57676 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
57677 			goto fail_not_writable;
57678 		}
57679 
57680 		DUK_DDD(DUK_DDDPRINT("base object is a string, start lookup from string prototype"));
57681 		curr = thr->builtins[DUK_BIDX_STRING_PROTOTYPE];
57682 		goto lookup;  /* avoid double coercion */
57683 	}
57684 
57685 	case DUK_TAG_OBJECT: {
57686 		orig = DUK_TVAL_GET_OBJECT(tv_obj);
57687 		DUK_ASSERT(orig != NULL);
57688 
57689 #if defined(DUK_USE_ROM_OBJECTS)
57690 		/* With this check in place fast paths won't need read-only
57691 		 * object checks.  This is technically incorrect if there are
57692 		 * setters that cause no writes to ROM objects, but current
57693 		 * built-ins don't have such setters.
57694 		 */
57695 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
57696 			DUK_DD(DUK_DDPRINT("attempt to putprop on read-only target object"));
57697 			goto fail_not_writable_no_pop;  /* Must avoid duk_pop() in exit path */
57698 		}
57699 #endif
57700 
57701 		/* The fast path for array property put is not fully compliant:
57702 		 * If one places conflicting number-indexed properties into
57703 		 * Array.prototype (for example, a non-writable Array.prototype[7])
57704 		 * the fast path will incorrectly ignore them.
57705 		 *
57706 		 * This fast path could be made compliant by falling through
57707 		 * to the slow path if the previous value was UNUSED.  This would
57708 		 * also remove the need to check for extensibility.  Right now a
57709 		 * non-extensible array is slower than an extensible one as far
57710 		 * as writes are concerned.
57711 		 *
57712 		 * The fast path behavior is documented in more detail here:
57713 		 * tests/ecmascript/test-misc-array-fast-write.js
57714 		 */
57715 
57716 		/* XXX: array .length? */
57717 
57718 #if defined(DUK_USE_ARRAY_PROP_FASTPATH)
57719 		if (duk__putprop_shallow_fastpath_array_tval(thr, orig, tv_key, tv_val) != 0) {
57720 			DUK_DDD(DUK_DDDPRINT("array fast path success"));
57721 			DUK_STATS_INC(thr->heap, stats_putprop_arrayidx);
57722 			return 1;
57723 		}
57724 #endif
57725 
57726 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
57727 		if (duk__putprop_fastpath_bufobj_tval(thr, orig, tv_key, tv_val) != 0) {
57728 			DUK_DDD(DUK_DDDPRINT("base is bufobj, key is a number, bufobj fast path"));
57729 			DUK_STATS_INC(thr->heap, stats_putprop_bufobjidx);
57730 			return 1;
57731 		}
57732 #endif
57733 
57734 #if defined(DUK_USE_ES6_PROXY)
57735 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(orig))) {
57736 			duk_hobject *h_target;
57737 			duk_bool_t tmp_bool;
57738 
57739 			if (duk__proxy_check_prop(thr, orig, DUK_STRIDX_SET, tv_key, &h_target)) {
57740 				/* -> [ ... trap handler ] */
57741 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'set' for key %!T", (duk_tval *) tv_key));
57742 				DUK_STATS_INC(thr->heap, stats_putprop_proxy);
57743 				duk_push_hobject(thr, h_target);  /* target */
57744 				duk_push_tval(thr, tv_key);       /* P */
57745 				duk_push_tval(thr, tv_val);       /* V */
57746 				duk_push_tval(thr, tv_obj);       /* Receiver: Proxy object */
57747 				duk_call_method(thr, 4 /*nargs*/);
57748 				tmp_bool = duk_to_boolean_top_pop(thr);
57749 				if (!tmp_bool) {
57750 					goto fail_proxy_rejected;
57751 				}
57752 
57753 				/* Target object must be checked for a conflicting
57754 				 * non-configurable property.
57755 				 */
57756 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57757 				DUK_ASSERT(key != NULL);
57758 
57759 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, DUK_GETDESC_FLAG_PUSH_VALUE)) {
57760 					duk_tval *tv_targ = duk_require_tval(thr, -1);
57761 					duk_bool_t datadesc_reject;
57762 					duk_bool_t accdesc_reject;
57763 
57764 					DUK_DDD(DUK_DDDPRINT("proxy 'set': target has matching property %!O, check for "
57765 					                     "conflicting property; tv_val=%!T, tv_targ=%!T, desc.flags=0x%08lx, "
57766 					                     "desc.get=%p, desc.set=%p",
57767 					                     (duk_heaphdr *) key, (duk_tval *) tv_val, (duk_tval *) tv_targ,
57768 					                     (unsigned long) desc.flags,
57769 					                     (void *) desc.get, (void *) desc.set));
57770 
57771 					datadesc_reject = !(desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57772 					                  !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57773 					                  !(desc.flags & DUK_PROPDESC_FLAG_WRITABLE) &&
57774 					                  !duk_js_samevalue(tv_val, tv_targ);
57775 					accdesc_reject = (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
57776 					                 !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) &&
57777 					                 (desc.set == NULL);
57778 					if (datadesc_reject || accdesc_reject) {
57779 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
57780 						DUK_WO_NORETURN(return 0;);
57781 					}
57782 
57783 					duk_pop_2_unsafe(thr);
57784 				} else {
57785 					duk_pop_unsafe(thr);
57786 				}
57787 				return 1;  /* success */
57788 			}
57789 
57790 			orig = h_target;  /* resume write to target */
57791 			DUK_TVAL_SET_OBJECT(tv_obj, orig);
57792 		}
57793 #endif  /* DUK_USE_ES6_PROXY */
57794 
57795 		curr = orig;
57796 		break;
57797 	}
57798 
57799 	case DUK_TAG_BUFFER: {
57800 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
57801 		duk_int_t pop_count = 0;
57802 
57803 		/*
57804 		 *  Because buffer values may be looped over and read/written
57805 		 *  from, an array index fast path is important.
57806 		 */
57807 
57808 #if defined(DUK_USE_FASTINT)
57809 		if (DUK_TVAL_IS_FASTINT(tv_key)) {
57810 			arr_idx = duk__tval_fastint_to_arr_idx(tv_key);
57811 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path fastint; arr_idx %ld", (long) arr_idx));
57812 			pop_count = 0;
57813 		} else
57814 #endif
57815 		if (DUK_TVAL_IS_NUMBER(tv_key)) {
57816 			arr_idx = duk__tval_number_to_arr_idx(tv_key);
57817 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a fast-path number; arr_idx %ld", (long) arr_idx));
57818 			pop_count = 0;
57819 		} else {
57820 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57821 			DUK_ASSERT(key != NULL);
57822 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57823 			                     "coercion key is %!T, arr_idx %ld",
57824 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57825 			pop_count = 1;
57826 		}
57827 
57828 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
57829 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
57830 			duk_uint8_t *data;
57831 			DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
57832 			data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h);
57833 
57834 			/* XXX: duk_to_int() ensures we'll get 8 lowest bits as
57835 			 * as input is within duk_int_t range (capped outside it).
57836 			 */
57837 #if defined(DUK_USE_FASTINT)
57838 			/* Buffer writes are often integers. */
57839 			if (DUK_TVAL_IS_FASTINT(tv_val)) {
57840 				data[arr_idx] = (duk_uint8_t) DUK_TVAL_GET_FASTINT_U32(tv_val);
57841 			}
57842 			else
57843 #endif
57844 			{
57845 				duk_push_tval(thr, tv_val);
57846 				data[arr_idx] = (duk_uint8_t) duk_to_uint32(thr, -1);
57847 				pop_count++;
57848 			}
57849 
57850 			duk_pop_n_unsafe(thr, pop_count);
57851 			DUK_DDD(DUK_DDDPRINT("result: success (buffer data write)"));
57852 			DUK_STATS_INC(thr->heap, stats_putprop_bufferidx);
57853 			return 1;
57854 		}
57855 
57856 		if (pop_count == 0) {
57857 			/* This is a pretty awkward control flow, but we need to recheck the
57858 			 * key coercion here.
57859 			 */
57860 			arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57861 			DUK_ASSERT(key != NULL);
57862 			DUK_DDD(DUK_DDDPRINT("base object buffer, key is a non-fast-path number; after "
57863 			                     "coercion key is %!T, arr_idx %ld",
57864 			                     (duk_tval *) duk_get_tval(thr, -1), (long) arr_idx));
57865 		}
57866 
57867 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
57868 			goto fail_not_writable;
57869 		}
57870 
57871 		DUK_DDD(DUK_DDDPRINT("base object is a buffer, start lookup from Uint8Array prototype"));
57872 		curr = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
57873 		goto lookup;  /* avoid double coercion */
57874 	}
57875 
57876 	case DUK_TAG_POINTER: {
57877 		DUK_DDD(DUK_DDDPRINT("base object is a pointer, start lookup from pointer prototype"));
57878 		curr = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
57879 		break;
57880 	}
57881 
57882 	case DUK_TAG_LIGHTFUNC: {
57883 		/* Lightfuncs have no own properties and are considered non-extensible.
57884 		 * However, the write may be captured by an inherited setter which
57885 		 * means we can't stop the lookup here.
57886 		 */
57887 		DUK_DDD(DUK_DDDPRINT("base object is a lightfunc, start lookup from function prototype"));
57888 		curr = thr->builtins[DUK_BIDX_NATIVE_FUNCTION_PROTOTYPE];
57889 		break;
57890 	}
57891 
57892 #if defined(DUK_USE_FASTINT)
57893 	case DUK_TAG_FASTINT:
57894 #endif
57895 	default: {
57896 		/* number */
57897 		DUK_DDD(DUK_DDDPRINT("base object is a number, start lookup from number prototype"));
57898 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_obj));
57899 		curr = thr->builtins[DUK_BIDX_NUMBER_PROTOTYPE];
57900 		break;
57901 	}
57902 	}
57903 
57904 	DUK_ASSERT(key == NULL);
57905 	arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
57906 	DUK_ASSERT(key != NULL);
57907 
57908  lookup:
57909 
57910 	/*
57911 	 *  Check whether the property already exists in the prototype chain.
57912 	 *  Note that the actual write goes into the original base object
57913 	 *  (except if an accessor property captures the write).
57914 	 */
57915 
57916 	/* [key] */
57917 
57918 	DUK_ASSERT(curr != NULL);
57919 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
57920 	do {
57921 		if (!duk__get_own_propdesc_raw(thr, curr, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
57922 			goto next_in_chain;
57923 		}
57924 
57925 		if (desc.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
57926 			/*
57927 			 *  Found existing accessor property (own or inherited).
57928 			 *  Call setter with 'this' set to orig, and value as the only argument.
57929 			 *  Setter calls are OK even for ROM objects.
57930 			 *
57931 			 *  Note: no exotic arguments object behavior, because [[Put]] never
57932 			 *  calls [[DefineOwnProperty]] (E5 Section 8.12.5, step 5.b).
57933 			 */
57934 
57935 			duk_hobject *setter;
57936 
57937 			DUK_DD(DUK_DDPRINT("put to an own or inherited accessor, calling setter"));
57938 
57939 			setter = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, curr, desc.e_idx);
57940 			if (!setter) {
57941 				goto fail_no_setter;
57942 			}
57943 			duk_push_hobject(thr, setter);
57944 			duk_push_tval(thr, tv_obj);  /* note: original, uncoerced base */
57945 			duk_push_tval(thr, tv_val);  /* [key setter this val] */
57946 #if defined(DUK_USE_NONSTD_SETTER_KEY_ARGUMENT)
57947 			duk_dup_m4(thr);
57948 			duk_call_method(thr, 2);     /* [key setter this val key] -> [key retval] */
57949 #else
57950 			duk_call_method(thr, 1);     /* [key setter this val] -> [key retval] */
57951 #endif
57952 			duk_pop_unsafe(thr);         /* ignore retval -> [key] */
57953 			goto success_no_arguments_exotic;
57954 		}
57955 
57956 		if (orig == NULL) {
57957 			/*
57958 			 *  Found existing own or inherited plain property, but original
57959 			 *  base is a primitive value.
57960 			 */
57961 			DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
57962 			goto fail_base_primitive;
57963 		}
57964 
57965 		if (curr != orig) {
57966 			/*
57967 			 *  Found existing inherited plain property.
57968 			 *  Do an access control check, and if OK, write
57969 			 *  new property to 'orig'.
57970 			 */
57971 			if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
57972 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, but original object is not extensible"));
57973 				goto fail_not_extensible;
57974 			}
57975 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
57976 				DUK_DD(DUK_DDPRINT("found existing inherited plain property, original object is extensible, but inherited property is not writable"));
57977 				goto fail_not_writable;
57978 			}
57979 			DUK_DD(DUK_DDPRINT("put to new property, object extensible, inherited property found and is writable"));
57980 			goto create_new;
57981 		} else {
57982 			/*
57983 			 *  Found existing own (non-inherited) plain property.
57984 			 *  Do an access control check and update in place.
57985 			 */
57986 
57987 			if (!(desc.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
57988 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) plain property, but property is not writable"));
57989 				goto fail_not_writable;
57990 			}
57991 			if (desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) {
57992 				DUK_DD(DUK_DDPRINT("found existing own (non-inherited) virtual property, property is writable"));
57993 
57994 				if (DUK_HOBJECT_IS_ARRAY(curr)) {
57995 					/*
57996 					 *  Write to 'length' of an array is a very complex case
57997 					 *  handled in a helper which updates both the array elements
57998 					 *  and writes the new 'length'.  The write may result in an
57999 					 *  unconditional RangeError or a partial write (indicated
58000 					 *  by a return code).
58001 					 *
58002 					 *  Note: the helper has an unnecessary writability check
58003 					 *  for 'length', we already know it is writable.
58004 					 */
58005 					DUK_ASSERT(key == DUK_HTHREAD_STRING_LENGTH(thr));  /* only virtual array property */
58006 
58007 					DUK_DDD(DUK_DDDPRINT("writing existing 'length' property to array exotic, invoke complex helper"));
58008 
58009 					/* XXX: the helper currently assumes stack top contains new
58010 					 * 'length' value and the whole calling convention is not very
58011 					 * compatible with what we need.
58012 					 */
58013 
58014 					duk_push_tval(thr, tv_val);  /* [key val] */
58015 					rc = duk__handle_put_array_length(thr, orig);
58016 					duk_pop_unsafe(thr);  /* [key val] -> [key] */
58017 					if (!rc) {
58018 						goto fail_array_length_partial;
58019 					}
58020 
58021 					/* key is 'length', cannot match argument exotic behavior */
58022 					goto success_no_arguments_exotic;
58023 				}
58024 #if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
58025 				else if (DUK_HOBJECT_IS_BUFOBJ(curr)) {
58026 					duk_hbufobj *h_bufobj;
58027 					duk_uint_t byte_off;
58028 					duk_small_uint_t elem_size;
58029 
58030 					h_bufobj = (duk_hbufobj *) curr;
58031 					DUK_ASSERT_HBUFOBJ_VALID(h_bufobj);
58032 
58033 					DUK_DD(DUK_DDPRINT("writable virtual property is in buffer object"));
58034 
58035 					/* Careful with wrapping: arr_idx upshift may easily wrap, whereas
58036 					 * length downshift won't.
58037 					 */
58038 					if (arr_idx < (h_bufobj->length >> h_bufobj->shift) && DUK_HBUFOBJ_HAS_VIRTUAL_INDICES(h_bufobj)) {
58039 						duk_uint8_t *data;
58040 						DUK_DDD(DUK_DDDPRINT("writing to buffer data at index %ld", (long) arr_idx));
58041 
58042 						DUK_ASSERT(arr_idx != DUK__NO_ARRAY_INDEX);  /* index/length check guarantees */
58043 						byte_off = arr_idx << h_bufobj->shift;       /* no wrap assuming h_bufobj->length is valid */
58044 						elem_size = (duk_small_uint_t) (1U << h_bufobj->shift);
58045 
58046 						/* Coerce to number before validating pointers etc so that the
58047 						 * number coercions in duk_hbufobj_validated_write() are
58048 						 * guaranteed to be side effect free and not invalidate the
58049 						 * pointer checks we do here.
58050 						 */
58051 						duk_push_tval(thr, tv_val);
58052 						(void) duk_to_number_m1(thr);
58053 
58054 						if (h_bufobj->buf != NULL && DUK_HBUFOBJ_VALID_BYTEOFFSET_EXCL(h_bufobj, byte_off + elem_size)) {
58055 							data = (duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(thr->heap, h_bufobj->buf) + h_bufobj->offset + byte_off;
58056 							duk_hbufobj_validated_write(thr, h_bufobj, data, elem_size);
58057 						} else {
58058 							DUK_D(DUK_DPRINT("bufobj access out of underlying buffer, ignoring (write skipped)"));
58059 						}
58060 						duk_pop_unsafe(thr);
58061 						goto success_no_arguments_exotic;
58062 					}
58063 				}
58064 #endif  /* DUK_USE_BUFFEROBJECT_SUPPORT */
58065 
58066 				DUK_D(DUK_DPRINT("should not happen, key %!O", key));
58067 				goto fail_internal;  /* should not happen */
58068 			}
58069 			DUK_DD(DUK_DDPRINT("put to existing own plain property, property is writable"));
58070 			goto update_old;
58071 		}
58072 		DUK_UNREACHABLE();
58073 
58074 	 next_in_chain:
58075 		/* XXX: option to pretend property doesn't exist if sanity limit is
58076 		 * hit might be useful.
58077 		 */
58078 		if (DUK_UNLIKELY(sanity-- == 0)) {
58079 			DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
58080 			DUK_WO_NORETURN(return 0;);
58081 		}
58082 		curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, curr);
58083 	} while (curr != NULL);
58084 
58085 	/*
58086 	 *  Property not found in prototype chain.
58087 	 */
58088 
58089 	DUK_DDD(DUK_DDDPRINT("property not found in prototype chain"));
58090 
58091 	if (orig == NULL) {
58092 		DUK_DD(DUK_DDPRINT("attempt to create a new property in a primitive base object"));
58093 		goto fail_base_primitive;
58094 	}
58095 
58096 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(orig)) {
58097 		DUK_DD(DUK_DDPRINT("put to a new property (not found in prototype chain), but original object not extensible"));
58098 		goto fail_not_extensible;
58099 	}
58100 
58101 	goto create_new;
58102 
58103  update_old:
58104 
58105 	/*
58106 	 *  Update an existing property of the base object.
58107 	 */
58108 
58109 	/* [key] */
58110 
58111 	DUK_DDD(DUK_DDDPRINT("update an existing property of the original object"));
58112 
58113 	DUK_ASSERT(orig != NULL);
58114 #if defined(DUK_USE_ROM_OBJECTS)
58115 	/* This should not happen because DUK_TAG_OBJECT case checks
58116 	 * for this already, but check just in case.
58117 	 */
58118 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58119 		goto fail_not_writable;
58120 	}
58121 #endif
58122 
58123 	/* Although there are writable virtual properties (e.g. plain buffer
58124 	 * and buffer object number indices), they are handled before we come
58125 	 * here.
58126 	 */
58127 	DUK_ASSERT((desc.flags & DUK_PROPDESC_FLAG_VIRTUAL) == 0);
58128 	DUK_ASSERT(desc.a_idx >= 0 || desc.e_idx >= 0);
58129 
58130 	/* Array own property .length is handled above. */
58131 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58132 
58133 	if (desc.e_idx >= 0) {
58134 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, desc.e_idx);
58135 		DUK_DDD(DUK_DDDPRINT("previous entry value: %!iT", (duk_tval *) tv));
58136 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; e_idx may be invalidated */
58137 		/* don't touch property attributes or hash part */
58138 		DUK_DD(DUK_DDPRINT("put to an existing entry at index %ld -> new value %!iT",
58139 		                   (long) desc.e_idx, (duk_tval *) tv));
58140 	} else {
58141 		/* Note: array entries are always writable, so the writability check
58142 		 * above is pointless for them.  The check could be avoided with some
58143 		 * refactoring but is probably not worth it.
58144 		 */
58145 
58146 		DUK_ASSERT(desc.a_idx >= 0);
58147 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, desc.a_idx);
58148 		DUK_DDD(DUK_DDDPRINT("previous array value: %!iT", (duk_tval *) tv));
58149 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv_val);  /* side effects; a_idx may be invalidated */
58150 		DUK_DD(DUK_DDPRINT("put to an existing array entry at index %ld -> new value %!iT",
58151 		                   (long) desc.a_idx, (duk_tval *) tv));
58152 	}
58153 
58154 	/* Regardless of whether property is found in entry or array part,
58155 	 * it may have arguments exotic behavior (array indices may reside
58156 	 * in entry part for abandoned / non-existent array parts).
58157 	 */
58158 	goto success_with_arguments_exotic;
58159 
58160  create_new:
58161 
58162 	/*
58163 	 *  Create a new property in the original object.
58164 	 *
58165 	 *  Exotic properties need to be reconsidered here from a write
58166 	 *  perspective (not just property attributes perspective).
58167 	 *  However, the property does not exist in the object already,
58168 	 *  so this limits the kind of exotic properties that apply.
58169 	 */
58170 
58171 	/* [key] */
58172 
58173 	DUK_DDD(DUK_DDDPRINT("create new property to original object"));
58174 
58175 	DUK_ASSERT(orig != NULL);
58176 
58177 	/* Array own property .length is handled above. */
58178 	DUK_ASSERT(!(DUK_HOBJECT_IS_ARRAY(orig) && key == DUK_HTHREAD_STRING_LENGTH(thr)));
58179 
58180 #if defined(DUK_USE_ROM_OBJECTS)
58181 	/* This should not happen because DUK_TAG_OBJECT case checks
58182 	 * for this already, but check just in case.
58183 	 */
58184 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) orig)) {
58185 		goto fail_not_writable;
58186 	}
58187 #endif
58188 
58189 	/* Not possible because array object 'length' is present
58190 	 * from its creation and cannot be deleted, and is thus
58191 	 * caught as an existing property above.
58192 	 */
58193 	DUK_ASSERT(!(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58194 	             key == DUK_HTHREAD_STRING_LENGTH(thr)));
58195 
58196 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig) &&
58197 	    arr_idx != DUK__NO_ARRAY_INDEX) {
58198 		/* automatic length update */
58199 		duk_uint32_t old_len;
58200 		duk_harray *a;
58201 
58202 		a = (duk_harray *) orig;
58203 		DUK_ASSERT_HARRAY_VALID(a);
58204 
58205 		old_len = a->length;
58206 
58207 		if (arr_idx >= old_len) {
58208 			DUK_DDD(DUK_DDDPRINT("write new array entry requires length update "
58209 			                     "(arr_idx=%ld, old_len=%ld)",
58210 			                     (long) arr_idx, (long) old_len));
58211 
58212 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a)) {
58213 				DUK_DD(DUK_DDPRINT("attempt to extend array, but array 'length' is not writable"));
58214 				goto fail_not_writable;
58215 			}
58216 
58217 			/* Note: actual update happens once write has been completed
58218 			 * without error below.  The write should always succeed
58219 			 * from a specification viewpoint, but we may e.g. run out
58220 			 * of memory.  It's safer in this order.
58221 			 */
58222 
58223 			DUK_ASSERT(arr_idx != 0xffffffffUL);
58224 			new_array_length = arr_idx + 1;  /* flag for later write */
58225 		} else {
58226 			DUK_DDD(DUK_DDDPRINT("write new array entry does not require length update "
58227 			                     "(arr_idx=%ld, old_len=%ld)",
58228 			                     (long) arr_idx, (long) old_len));
58229 		}
58230 	}
58231 
58232  /* write_to_array_part: */
58233 
58234 	/*
58235 	 *  Write to array part?
58236 	 *
58237 	 *  Note: array abandonding requires a property resize which uses
58238 	 *  'rechecks' valstack for temporaries and may cause any existing
58239 	 *  valstack pointers to be invalidated.  To protect against this,
58240 	 *  tv_obj, tv_key, and tv_val are copies of the original inputs.
58241 	 */
58242 
58243 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
58244 	    DUK_HOBJECT_HAS_ARRAY_PART(orig)) {
58245 		if (arr_idx < DUK_HOBJECT_GET_ASIZE(orig)) {
58246 			goto no_array_growth;
58247 		}
58248 
58249 		/*
58250 		 *  Array needs to grow, but we don't want it becoming too sparse.
58251 		 *  If it were to become sparse, abandon array part, moving all
58252 		 *  array entries into the entries part (for good).
58253 		 *
58254 		 *  Since we don't keep track of actual density (used vs. size) of
58255 		 *  the array part, we need to estimate somehow.  The check is made
58256 		 *  in two parts:
58257 		 *
58258 		 *    - Check whether the resize need is small compared to the
58259 		 *      current size (relatively); if so, resize without further
58260 		 *      checking (essentially we assume that the original part is
58261 		 *      "dense" so that the result would be dense enough).
58262 		 *
58263 		 *    - Otherwise, compute the resize using an actual density
58264 		 *      measurement based on counting the used array entries.
58265 		 */
58266 
58267 		DUK_DDD(DUK_DDDPRINT("write to new array requires array resize, decide whether to do a "
58268 		                     "fast resize without abandon check (arr_idx=%ld, old_size=%ld)",
58269 		                     (long) arr_idx, (long) DUK_HOBJECT_GET_ASIZE(orig)));
58270 
58271 		if (duk__abandon_array_slow_check_required(arr_idx, DUK_HOBJECT_GET_ASIZE(orig))) {
58272 			duk_uint32_t old_used;
58273 			duk_uint32_t old_size;
58274 
58275 			DUK_DDD(DUK_DDDPRINT("=> fast check is NOT OK, do slow check for array abandon"));
58276 
58277 			duk__compute_a_stats(thr, orig, &old_used, &old_size);
58278 
58279 			DUK_DDD(DUK_DDDPRINT("abandon check, array stats: old_used=%ld, old_size=%ld, arr_idx=%ld",
58280 			                     (long) old_used, (long) old_size, (long) arr_idx));
58281 
58282 			/* Note: intentionally use approximations to shave a few instructions:
58283 			 *   a_used = old_used  (accurate: old_used + 1)
58284 			 *   a_size = arr_idx   (accurate: arr_idx + 1)
58285 			 */
58286 			if (duk__abandon_array_density_check(old_used, arr_idx)) {
58287 				DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58288 				                   "decided to abandon array part (would become too sparse)"));
58289 
58290 				/* abandoning requires a props allocation resize and
58291 				 * 'rechecks' the valstack, invalidating any existing
58292 				 * valstack value pointers!
58293 				 */
58294 				duk__abandon_array_checked(thr, orig);
58295 				DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(orig));
58296 
58297 				goto write_to_entry_part;
58298 			}
58299 
58300 			DUK_DDD(DUK_DDDPRINT("=> decided to keep array part"));
58301 		} else {
58302 			DUK_DDD(DUK_DDDPRINT("=> fast resize is OK"));
58303 		}
58304 
58305 		DUK_DD(DUK_DDPRINT("write to new array entry beyond current length, "
58306 		                   "decided to extend current allocation"));
58307 
58308 		duk__grow_props_for_array_item(thr, orig, arr_idx);
58309 
58310 	 no_array_growth:
58311 
58312 		/* Note: assume array part is comprehensive, so that either
58313 		 * the write goes to the array part, or we've abandoned the
58314 		 * array above (and will not come here).
58315 		 */
58316 
58317 		DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(orig));
58318 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(orig));
58319 
58320 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, orig, arr_idx);
58321 		/* prev value must be unused, no decref */
58322 		DUK_ASSERT(DUK_TVAL_IS_UNUSED(tv));
58323 		DUK_TVAL_SET_TVAL(tv, tv_val);
58324 		DUK_TVAL_INCREF(thr, tv);
58325 		DUK_DD(DUK_DDPRINT("put to new array entry: %ld -> %!T",
58326 		                   (long) arr_idx, (duk_tval *) tv));
58327 
58328 		/* Note: array part values are [[Writable]], [[Enumerable]],
58329 		 * and [[Configurable]] which matches the required attributes
58330 		 * here.
58331 		 */
58332 		goto entry_updated;
58333 	}
58334 
58335  write_to_entry_part:
58336 
58337 	/*
58338 	 *  Write to entry part
58339 	 */
58340 
58341 	/* entry allocation updates hash part and increases the key
58342 	 * refcount; may need a props allocation resize but doesn't
58343 	 * 'recheck' the valstack.
58344 	 */
58345 	e_idx = duk__hobject_alloc_entry_checked(thr, orig, key);
58346 	DUK_ASSERT(e_idx >= 0);
58347 
58348 	tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, orig, e_idx);
58349 	/* prev value can be garbage, no decref */
58350 	DUK_TVAL_SET_TVAL(tv, tv_val);
58351 	DUK_TVAL_INCREF(thr, tv);
58352 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, orig, e_idx, DUK_PROPDESC_FLAGS_WEC);
58353 	goto entry_updated;
58354 
58355  entry_updated:
58356 
58357 	/*
58358 	 *  Possible pending array length update, which must only be done
58359 	 *  if the actual entry write succeeded.
58360 	 */
58361 
58362 	if (new_array_length > 0) {
58363 		/* Note: zero works as a "no update" marker because the new length
58364 		 * can never be zero after a new property is written.
58365 		 */
58366 
58367 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(orig));
58368 
58369 		DUK_DDD(DUK_DDDPRINT("write successful, pending array length update to: %ld",
58370 		                     (long) new_array_length));
58371 
58372 		((duk_harray *) orig)->length = new_array_length;
58373 	}
58374 
58375 	/*
58376 	 *  Arguments exotic behavior not possible for new properties: all
58377 	 *  magically bound properties are initially present in the arguments
58378 	 *  object, and if they are deleted, the binding is also removed from
58379 	 *  parameter map.
58380 	 */
58381 
58382 	goto success_no_arguments_exotic;
58383 
58384  success_with_arguments_exotic:
58385 
58386 	/*
58387 	 *  Arguments objects have exotic [[DefineOwnProperty]] which updates
58388 	 *  the internal 'map' of arguments for writes to currently mapped
58389 	 *  arguments.  More conretely, writes to mapped arguments generate
58390 	 *  a write to a bound variable.
58391 	 *
58392 	 *  The [[Put]] algorithm invokes [[DefineOwnProperty]] for existing
58393 	 *  data properties and new properties, but not for existing accessors.
58394 	 *  Hence, in E5 Section 10.6 ([[DefinedOwnProperty]] algorithm), we
58395 	 *  have a Desc with 'Value' (and possibly other properties too), and
58396 	 *  we end up in step 5.b.i.
58397 	 */
58398 
58399 	if (arr_idx != DUK__NO_ARRAY_INDEX &&
58400 	    DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(orig)) {
58401 		/* Note: only numbered indices are relevant, so arr_idx fast reject
58402 		 * is good (this is valid unless there are more than 4**32-1 arguments).
58403 		 */
58404 
58405 		DUK_DDD(DUK_DDDPRINT("putprop successful, arguments exotic behavior needed"));
58406 
58407 		/* Note: we can reuse 'desc' here */
58408 
58409 		/* XXX: top of stack must contain value, which helper doesn't touch,
58410 		 * rework to use tv_val directly?
58411 		 */
58412 
58413 		duk_push_tval(thr, tv_val);
58414 		(void) duk__check_arguments_map_for_put(thr, orig, key, &desc, throw_flag);
58415 		duk_pop_unsafe(thr);
58416 	}
58417 	/* fall thru */
58418 
58419  success_no_arguments_exotic:
58420 	/* shared exit path now */
58421 	DUK_DDD(DUK_DDDPRINT("result: success"));
58422 	duk_pop_unsafe(thr);  /* remove key */
58423 	return 1;
58424 
58425 #if defined(DUK_USE_ES6_PROXY)
58426  fail_proxy_rejected:
58427 	DUK_DDD(DUK_DDDPRINT("result: error, proxy rejects"));
58428 	if (throw_flag) {
58429 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58430 		DUK_WO_NORETURN(return 0;);
58431 	}
58432 	/* Note: no key on stack */
58433 	return 0;
58434 #endif
58435 
58436  fail_base_primitive:
58437 	DUK_DDD(DUK_DDDPRINT("result: error, base primitive"));
58438 	if (throw_flag) {
58439 #if defined(DUK_USE_PARANOID_ERRORS)
58440 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58441 #else
58442 		DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot write property %s of %s",
58443 		               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
58444 #endif
58445 		DUK_WO_NORETURN(return 0;);
58446 	}
58447 	duk_pop_unsafe(thr);  /* remove key */
58448 	return 0;
58449 
58450  fail_not_extensible:
58451 	DUK_DDD(DUK_DDDPRINT("result: error, not extensible"));
58452 	if (throw_flag) {
58453 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
58454 		DUK_WO_NORETURN(return 0;);
58455 	}
58456 	duk_pop_unsafe(thr);  /* remove key */
58457 	return 0;
58458 
58459  fail_not_writable:
58460 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
58461 	if (throw_flag) {
58462 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
58463 		DUK_WO_NORETURN(return 0;);
58464 	}
58465 	duk_pop_unsafe(thr);  /* remove key */
58466 	return 0;
58467 
58468 #if defined(DUK_USE_ROM_OBJECTS)
58469  fail_not_writable_no_pop:
58470 	DUK_DDD(DUK_DDDPRINT("result: error, not writable"));
58471 	if (throw_flag) {
58472 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_WRITABLE);
58473 		DUK_WO_NORETURN(return 0;);
58474 	}
58475 	return 0;
58476 #endif
58477 
58478  fail_array_length_partial:
58479 	DUK_DD(DUK_DDPRINT("result: error, array length write only partially successful"));
58480 	if (throw_flag) {
58481 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58482 		DUK_WO_NORETURN(return 0;);
58483 	}
58484 	duk_pop_unsafe(thr);  /* remove key */
58485 	return 0;
58486 
58487  fail_no_setter:
58488 	DUK_DDD(DUK_DDDPRINT("result: error, accessor property without setter"));
58489 	if (throw_flag) {
58490 		DUK_ERROR_TYPE(thr, DUK_STR_SETTER_UNDEFINED);
58491 		DUK_WO_NORETURN(return 0;);
58492 	}
58493 	duk_pop_unsafe(thr);  /* remove key */
58494 	return 0;
58495 
58496  fail_internal:
58497 	DUK_DDD(DUK_DDDPRINT("result: error, internal"));
58498 	if (throw_flag) {
58499 		DUK_ERROR_INTERNAL(thr);
58500 		DUK_WO_NORETURN(return 0;);
58501 	}
58502 	duk_pop_unsafe(thr);  /* remove key */
58503 	return 0;
58504 }
58505 
58506 /*
58507  *  ECMAScript compliant [[Delete]](P, Throw).
58508  */
58509 
58510 DUK_INTERNAL duk_bool_t duk_hobject_delprop_raw(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
58511 	duk_propdesc desc;
58512 	duk_tval *tv;
58513 	duk_uint32_t arr_idx;
58514 	duk_bool_t throw_flag;
58515 	duk_bool_t force_flag;
58516 
58517 	throw_flag = (flags & DUK_DELPROP_FLAG_THROW);
58518 	force_flag = (flags & DUK_DELPROP_FLAG_FORCE);
58519 
58520 	DUK_DDD(DUK_DDDPRINT("delprop_raw: thr=%p, obj=%p, key=%p, throw=%ld, force=%ld (obj -> %!O, key -> %!O)",
58521 	                     (void *) thr, (void *) obj, (void *) key, (long) throw_flag, (long) force_flag,
58522 	                     (duk_heaphdr *) obj, (duk_heaphdr *) key));
58523 
58524 	DUK_ASSERT(thr != NULL);
58525 	DUK_ASSERT(thr->heap != NULL);
58526 	DUK_ASSERT(obj != NULL);
58527 	DUK_ASSERT(key != NULL);
58528 
58529 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58530 
58531 	arr_idx = DUK_HSTRING_GET_ARRIDX_FAST(key);
58532 
58533 	/* 0 = don't push current value */
58534 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58535 		DUK_DDD(DUK_DDDPRINT("property not found, succeed always"));
58536 		goto success;
58537 	}
58538 
58539 #if defined(DUK_USE_ROM_OBJECTS)
58540 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
58541 		DUK_DD(DUK_DDPRINT("attempt to delprop on read-only target object"));
58542 		goto fail_not_configurable;
58543 	}
58544 #endif
58545 
58546 	if ((desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) == 0 && !force_flag) {
58547 		goto fail_not_configurable;
58548 	}
58549 	if (desc.a_idx < 0 && desc.e_idx < 0) {
58550 		/* Currently there are no deletable virtual properties, but
58551 		 * with force_flag we might attempt to delete one.
58552 		 */
58553 		DUK_DD(DUK_DDPRINT("delete failed: property found, force flag, but virtual (and implicitly non-configurable)"));
58554 		goto fail_virtual;
58555 	}
58556 
58557 	if (desc.a_idx >= 0) {
58558 		DUK_ASSERT(desc.e_idx < 0);
58559 
58560 		tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
58561 		DUK_TVAL_SET_UNUSED_UPDREF(thr, tv);  /* side effects */
58562 		goto success;
58563 	} else {
58564 		DUK_ASSERT(desc.a_idx < 0);
58565 
58566 		/* remove hash entry (no decref) */
58567 #if defined(DUK_USE_HOBJECT_HASH_PART)
58568 		if (desc.h_idx >= 0) {
58569 			duk_uint32_t *h_base = DUK_HOBJECT_H_GET_BASE(thr->heap, obj);
58570 
58571 			DUK_DDD(DUK_DDDPRINT("removing hash entry at h_idx %ld", (long) desc.h_idx));
58572 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) > 0);
58573 			DUK_ASSERT((duk_uint32_t) desc.h_idx < DUK_HOBJECT_GET_HSIZE(obj));
58574 			h_base[desc.h_idx] = DUK__HASH_DELETED;
58575 		} else {
58576 			DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
58577 		}
58578 #else
58579 		DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(obj) == 0);
58580 #endif
58581 
58582 		/* Remove value.  This requires multiple writes so avoid side
58583 		 * effects via no-refzero macros so that e_idx is not
58584 		 * invalidated.
58585 		 */
58586 		DUK_DDD(DUK_DDDPRINT("before removing value, e_idx %ld, key %p, key at slot %p",
58587 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
58588 		DUK_DDD(DUK_DDDPRINT("removing value at e_idx %ld", (long) desc.e_idx));
58589 		if (DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx)) {
58590 			duk_hobject *tmp;
58591 
58592 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, desc.e_idx);
58593 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, desc.e_idx, NULL);
58594 			DUK_UNREF(tmp);
58595 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
58596 
58597 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, desc.e_idx);
58598 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, desc.e_idx, NULL);
58599 			DUK_UNREF(tmp);
58600 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
58601 		} else {
58602 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
58603 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv);
58604 		}
58605 #if 0
58606 		/* Not strictly necessary because if key == NULL, flag MUST be ignored. */
58607 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, 0);
58608 #endif
58609 
58610 		/* Remove key. */
58611 		DUK_DDD(DUK_DDDPRINT("before removing key, e_idx %ld, key %p, key at slot %p",
58612 		                     (long) desc.e_idx, (void *) key, (void *) DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx)));
58613 		DUK_DDD(DUK_DDDPRINT("removing key at e_idx %ld", (long) desc.e_idx));
58614 		DUK_ASSERT(key == DUK_HOBJECT_E_GET_KEY(thr->heap, obj, desc.e_idx));
58615 		DUK_HOBJECT_E_SET_KEY(thr->heap, obj, desc.e_idx, NULL);
58616 		DUK_HSTRING_DECREF_NORZ(thr, key);
58617 
58618 		/* Trigger refzero side effects only when we're done as a
58619 		 * finalizer might operate on the object and affect the
58620 		 * e_idx we're supposed to use.
58621 		 */
58622 		DUK_REFZERO_CHECK_SLOW(thr);
58623 		goto success;
58624 	}
58625 
58626 	DUK_UNREACHABLE();
58627 
58628  success:
58629 	/*
58630 	 *  Argument exotic [[Delete]] behavior (E5 Section 10.6) is
58631 	 *  a post-check, keeping arguments internal 'map' in sync with
58632 	 *  any successful deletes (note that property does not need to
58633 	 *  exist for delete to 'succeed').
58634 	 *
58635 	 *  Delete key from 'map'.  Since 'map' only contains array index
58636 	 *  keys, we can use arr_idx for a fast skip.
58637 	 */
58638 
58639 	DUK_DDD(DUK_DDDPRINT("delete successful, check for arguments exotic behavior"));
58640 
58641 	if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
58642 		/* Note: only numbered indices are relevant, so arr_idx fast reject
58643 		 * is good (this is valid unless there are more than 4**32-1 arguments).
58644 		 */
58645 
58646 		DUK_DDD(DUK_DDDPRINT("delete successful, arguments exotic behavior needed"));
58647 
58648 		/* Note: we can reuse 'desc' here */
58649 		(void) duk__check_arguments_map_for_delete(thr, obj, key, &desc);
58650 	}
58651 
58652 	DUK_DDD(DUK_DDDPRINT("delete successful"));
58653 	return 1;
58654 
58655  fail_virtual:  /* just use the same "not configurable" error message */
58656  fail_not_configurable:
58657 	DUK_DDD(DUK_DDDPRINT("delete failed: property found, not configurable"));
58658 
58659 	if (throw_flag) {
58660 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58661 		DUK_WO_NORETURN(return 0;);
58662 	}
58663 	return 0;
58664 }
58665 
58666 /*
58667  *  DELPROP: ECMAScript property deletion.
58668  */
58669 
58670 DUK_INTERNAL duk_bool_t duk_hobject_delprop(duk_hthread *thr, duk_tval *tv_obj, duk_tval *tv_key, duk_bool_t throw_flag) {
58671 	duk_hstring *key = NULL;
58672 #if defined(DUK_USE_ES6_PROXY)
58673 	duk_propdesc desc;
58674 #endif
58675 	duk_int_t entry_top;
58676 	duk_uint32_t arr_idx = DUK__NO_ARRAY_INDEX;
58677 	duk_bool_t rc;
58678 
58679 	DUK_DDD(DUK_DDDPRINT("delprop: thr=%p, obj=%p, key=%p (obj -> %!T, key -> %!T)",
58680 	                     (void *) thr, (void *) tv_obj, (void *) tv_key,
58681 	                     (duk_tval *) tv_obj, (duk_tval *) tv_key));
58682 
58683 	DUK_ASSERT(thr != NULL);
58684 	DUK_ASSERT(thr->heap != NULL);
58685 	DUK_ASSERT(tv_obj != NULL);
58686 	DUK_ASSERT(tv_key != NULL);
58687 
58688 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58689 
58690 	/* Storing the entry top is cheaper here to ensure stack is correct at exit,
58691 	 * as there are several paths out.
58692 	 */
58693 	entry_top = duk_get_top(thr);
58694 
58695 	if (DUK_TVAL_IS_UNDEFINED(tv_obj) ||
58696 	    DUK_TVAL_IS_NULL(tv_obj)) {
58697 		DUK_DDD(DUK_DDDPRINT("base object is undefined or null -> reject"));
58698 		goto fail_invalid_base_uncond;
58699 	}
58700 
58701 	duk_push_tval(thr, tv_obj);
58702 	duk_push_tval(thr, tv_key);
58703 
58704 	tv_obj = DUK_GET_TVAL_NEGIDX(thr, -2);
58705 	if (DUK_TVAL_IS_OBJECT(tv_obj)) {
58706 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_obj);
58707 		DUK_ASSERT(obj != NULL);
58708 
58709 #if defined(DUK_USE_ES6_PROXY)
58710 		if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(obj))) {
58711 			duk_hobject *h_target;
58712 			duk_bool_t tmp_bool;
58713 
58714 			/* Note: proxy handling must happen before key is string coerced. */
58715 
58716 			if (duk__proxy_check_prop(thr, obj, DUK_STRIDX_DELETE_PROPERTY, tv_key, &h_target)) {
58717 				/* -> [ ... obj key trap handler ] */
58718 				DUK_DDD(DUK_DDDPRINT("-> proxy object 'deleteProperty' for key %!T", (duk_tval *) tv_key));
58719 				duk_push_hobject(thr, h_target);  /* target */
58720 				duk_dup_m4(thr);  /* P */
58721 				duk_call_method(thr, 2 /*nargs*/);
58722 				tmp_bool = duk_to_boolean_top_pop(thr);
58723 				if (!tmp_bool) {
58724 					goto fail_proxy_rejected;  /* retval indicates delete failed */
58725 				}
58726 
58727 				/* Target object must be checked for a conflicting
58728 				 * non-configurable property.
58729 				 */
58730 				tv_key = DUK_GET_TVAL_NEGIDX(thr, -1);
58731 				arr_idx = duk__push_tval_to_property_key(thr, tv_key, &key);
58732 				DUK_ASSERT(key != NULL);
58733 
58734 				if (duk__get_own_propdesc_raw(thr, h_target, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58735 					duk_small_int_t desc_reject;
58736 
58737 					DUK_DDD(DUK_DDDPRINT("proxy 'deleteProperty': target has matching property %!O, check for "
58738 					                     "conflicting property; desc.flags=0x%08lx, "
58739 					                     "desc.get=%p, desc.set=%p",
58740 					                     (duk_heaphdr *) key, (unsigned long) desc.flags,
58741 					                     (void *) desc.get, (void *) desc.set));
58742 
58743 					desc_reject = !(desc.flags & DUK_PROPDESC_FLAG_CONFIGURABLE);
58744 					if (desc_reject) {
58745 						/* unconditional */
58746 						DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58747 						DUK_WO_NORETURN(return 0;);
58748 					}
58749 				}
58750 				rc = 1;  /* success */
58751 				goto done_rc;
58752 			}
58753 
58754 			obj = h_target;  /* resume delete to target */
58755 		}
58756 #endif  /* DUK_USE_ES6_PROXY */
58757 
58758 		arr_idx = duk__to_property_key(thr, -1, &key);
58759 		DUK_ASSERT(key != NULL);
58760 
58761 		rc = duk_hobject_delprop_raw(thr, obj, key, throw_flag ? DUK_DELPROP_FLAG_THROW : 0);
58762 		goto done_rc;
58763 	} else if (DUK_TVAL_IS_STRING(tv_obj)) {
58764 		/* String has .length and array index virtual properties
58765 		 * which can't be deleted.  No need for a symbol check;
58766 		 * no offending virtual symbols exist.
58767 		 */
58768 		/* XXX: unnecessary string coercion for array indices,
58769 		 * intentional to keep small.
58770 		 */
58771 		duk_hstring *h = DUK_TVAL_GET_STRING(tv_obj);
58772 		DUK_ASSERT(h != NULL);
58773 
58774 		arr_idx = duk__to_property_key(thr, -1, &key);
58775 		DUK_ASSERT(key != NULL);
58776 
58777 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58778 			goto fail_not_configurable;
58779 		}
58780 
58781 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58782 		    arr_idx < DUK_HSTRING_GET_CHARLEN(h)) {
58783 			goto fail_not_configurable;
58784 		}
58785 	} else if (DUK_TVAL_IS_BUFFER(tv_obj)) {
58786 		/* XXX: unnecessary string coercion for array indices,
58787 		 * intentional to keep small; some overlap with string
58788 		 * handling.
58789 		 */
58790 		duk_hbuffer *h = DUK_TVAL_GET_BUFFER(tv_obj);
58791 		DUK_ASSERT(h != NULL);
58792 
58793 		arr_idx = duk__to_property_key(thr, -1, &key);
58794 		DUK_ASSERT(key != NULL);
58795 
58796 		if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
58797 			goto fail_not_configurable;
58798 		}
58799 
58800 		if (arr_idx != DUK__NO_ARRAY_INDEX &&
58801 		    arr_idx < DUK_HBUFFER_GET_SIZE(h)) {
58802 			goto fail_not_configurable;
58803 		}
58804 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_obj)) {
58805 		/* Lightfunc has no virtual properties since Duktape 2.2
58806 		 * so success.  Still must coerce key for side effects.
58807 		 */
58808 
58809 		arr_idx = duk__to_property_key(thr, -1, &key);
58810 		DUK_ASSERT(key != NULL);
58811 		DUK_UNREF(key);
58812 	}
58813 
58814 	/* non-object base, no offending virtual property */
58815 	rc = 1;
58816 	goto done_rc;
58817 
58818  done_rc:
58819 	duk_set_top_unsafe(thr, entry_top);
58820 	return rc;
58821 
58822  fail_invalid_base_uncond:
58823 	/* Note: unconditional throw */
58824 	DUK_ASSERT(duk_get_top(thr) == entry_top);
58825 #if defined(DUK_USE_PARANOID_ERRORS)
58826 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_BASE);
58827 #else
58828 	DUK_ERROR_FMT2(thr, DUK_ERR_TYPE_ERROR, "cannot delete property %s of %s",
58829 	               duk_push_string_tval_readable(thr, tv_key), duk_push_string_tval_readable(thr, tv_obj));
58830 #endif
58831 	DUK_WO_NORETURN(return 0;);
58832 
58833 #if defined(DUK_USE_ES6_PROXY)
58834  fail_proxy_rejected:
58835 	if (throw_flag) {
58836 		DUK_ERROR_TYPE(thr, DUK_STR_PROXY_REJECTED);
58837 		DUK_WO_NORETURN(return 0;);
58838 	}
58839 	duk_set_top_unsafe(thr, entry_top);
58840 	return 0;
58841 #endif
58842 
58843  fail_not_configurable:
58844 	if (throw_flag) {
58845 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
58846 		DUK_WO_NORETURN(return 0;);
58847 	}
58848 	duk_set_top_unsafe(thr, entry_top);
58849 	return 0;
58850 }
58851 
58852 /*
58853  *  Internal helper to define a property with specific flags, ignoring
58854  *  normal semantics such as extensibility, write protection etc.
58855  *  Overwrites any existing value and attributes unless caller requests
58856  *  that value only be updated if it doesn't already exists.
58857  *
58858  *  Does not support:
58859  *    - virtual properties (error if write attempted)
58860  *    - getter/setter properties (error if write attempted)
58861  *    - non-default (!= WEC) attributes for array entries (error if attempted)
58862  *    - array abandoning: if array part exists, it is always extended
58863  *    - array 'length' updating
58864  *
58865  *  Stack: [... in_val] -> []
58866  *
58867  *  Used for e.g. built-in initialization and environment record
58868  *  operations.
58869  */
58870 
58871 DUK_INTERNAL void duk_hobject_define_property_internal(duk_hthread *thr, duk_hobject *obj, duk_hstring *key, duk_small_uint_t flags) {
58872 	duk_propdesc desc;
58873 	duk_uint32_t arr_idx;
58874 	duk_int_t e_idx;
58875 	duk_tval *tv1 = NULL;
58876 	duk_tval *tv2 = NULL;
58877 	duk_small_uint_t propflags = flags & DUK_PROPDESC_FLAGS_MASK;  /* mask out flags not actually stored */
58878 
58879 	DUK_DDD(DUK_DDDPRINT("define new property (internal): thr=%p, obj=%!O, key=%!O, flags=0x%02lx, val=%!T",
58880 	                     (void *) thr, (duk_heaphdr *) obj, (duk_heaphdr *) key,
58881 	                     (unsigned long) flags, (duk_tval *) duk_get_tval(thr, -1)));
58882 
58883 	DUK_ASSERT(thr != NULL);
58884 	DUK_ASSERT(thr->heap != NULL);
58885 	DUK_ASSERT(obj != NULL);
58886 	DUK_ASSERT(key != NULL);
58887 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
58888 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
58889 	DUK_ASSERT(duk_is_valid_index(thr, -1));  /* contains value */
58890 
58891 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
58892 
58893 	if (duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &desc, 0 /*flags*/)) {  /* don't push value */
58894 		if (desc.e_idx >= 0) {
58895 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58896 				DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> skip as requested"));
58897 				goto pop_exit;
58898 			}
58899 			DUK_DDD(DUK_DDDPRINT("property already exists in the entry part -> update value and attributes"));
58900 			if (DUK_UNLIKELY(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, desc.e_idx))) {
58901 				DUK_D(DUK_DPRINT("existing property is an accessor, not supported"));
58902 				goto error_internal;
58903 			}
58904 
58905 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, desc.e_idx, propflags);
58906 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, desc.e_idx);
58907 		} else if (desc.a_idx >= 0) {
58908 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58909 				DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> skip as requested"));
58910 				goto pop_exit;
58911 			}
58912 			DUK_DDD(DUK_DDDPRINT("property already exists in the array part -> update value (assert attributes)"));
58913 			if (propflags != DUK_PROPDESC_FLAGS_WEC) {
58914 				DUK_D(DUK_DPRINT("existing property in array part, but propflags not WEC (0x%02lx)",
58915 				                 (unsigned long) propflags));
58916 				goto error_internal;
58917 			}
58918 
58919 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, desc.a_idx);
58920 		} else {
58921 			if (flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) {
58922 				DUK_DDD(DUK_DDDPRINT("property already exists but is virtual -> skip as requested"));
58923 				goto pop_exit;
58924 			}
58925 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
58926 				duk_uint32_t new_len;
58927 #if defined(DUK_USE_DEBUG)
58928 				duk_uint32_t prev_len;
58929 				prev_len = ((duk_harray *) obj)->length;
58930 #endif
58931 				new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_NEGIDX(thr, -1));
58932 				((duk_harray *) obj)->length = new_len;
58933 				DUK_D(DUK_DPRINT("internal define property for array .length: %ld -> %ld",
58934 				                 (long) prev_len, (long) ((duk_harray *) obj)->length));
58935 				goto pop_exit;
58936 			}
58937 			DUK_DD(DUK_DDPRINT("property already exists but is virtual -> failure"));
58938 			goto error_virtual;
58939 		}
58940 
58941 		goto write_value;
58942 	}
58943 
58944 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
58945 		if (arr_idx != DUK__NO_ARRAY_INDEX) {
58946 			DUK_DDD(DUK_DDDPRINT("property does not exist, object has array part -> possibly extend array part and write value (assert attributes)"));
58947 			DUK_ASSERT(propflags == DUK_PROPDESC_FLAGS_WEC);
58948 
58949 			/* always grow the array, no sparse / abandon support here */
58950 			if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
58951 				duk__grow_props_for_array_item(thr, obj, arr_idx);
58952 			}
58953 
58954 			DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
58955 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
58956 			goto write_value;
58957 		}
58958 	}
58959 
58960 	DUK_DDD(DUK_DDDPRINT("property does not exist, object belongs in entry part -> allocate new entry and write value and attributes"));
58961 	e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);  /* increases key refcount */
58962 	DUK_ASSERT(e_idx >= 0);
58963 	DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, propflags);
58964 	tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
58965 	/* new entry: previous value is garbage; set to undefined to share write_value */
58966 	DUK_TVAL_SET_UNDEFINED(tv1);
58967 	goto write_value;
58968 
58969  write_value:
58970 	/* tv1 points to value storage */
58971 
58972 	tv2 = duk_require_tval(thr, -1);  /* late lookup, avoid side effects */
58973 	DUK_DDD(DUK_DDDPRINT("writing/updating value: %!T -> %!T",
58974 	                     (duk_tval *) tv1, (duk_tval *) tv2));
58975 
58976 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
58977 	goto pop_exit;
58978 
58979  pop_exit:
58980 	duk_pop_unsafe(thr);  /* remove in_val */
58981 	return;
58982 
58983  error_virtual:  /* share error message */
58984  error_internal:
58985 	DUK_ERROR_INTERNAL(thr);
58986 	DUK_WO_NORETURN(return;);
58987 }
58988 
58989 /*
58990  *  Fast path for defining array indexed values without interning the key.
58991  *  This is used by e.g. code for Array prototype and traceback creation so
58992  *  must avoid interning.
58993  */
58994 
58995 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) {
58996 	duk_hstring *key;
58997 	duk_tval *tv1, *tv2;
58998 
58999 	DUK_DDD(DUK_DDDPRINT("define new property (internal) arr_idx fast path: thr=%p, obj=%!O, "
59000 	                     "arr_idx=%ld, flags=0x%02lx, val=%!T",
59001 	                     (void *) thr, obj, (long) arr_idx, (unsigned long) flags,
59002 	                     (duk_tval *) duk_get_tval(thr, -1)));
59003 
59004 	DUK_ASSERT(thr != NULL);
59005 	DUK_ASSERT(thr->heap != NULL);
59006 	DUK_ASSERT(obj != NULL);
59007 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
59008 
59009 	if (DUK_HOBJECT_HAS_ARRAY_PART(obj) &&
59010 	    arr_idx != DUK__NO_ARRAY_INDEX &&
59011 	    flags == DUK_PROPDESC_FLAGS_WEC) {
59012 		DUK_ASSERT((flags & DUK_PROPDESC_FLAG_NO_OVERWRITE) == 0);  /* covered by comparison */
59013 
59014 		DUK_DDD(DUK_DDDPRINT("define property to array part (property may or may not exist yet)"));
59015 
59016 		/* always grow the array, no sparse / abandon support here */
59017 		if (arr_idx >= DUK_HOBJECT_GET_ASIZE(obj)) {
59018 			duk__grow_props_for_array_item(thr, obj, arr_idx);
59019 		}
59020 
59021 		DUK_ASSERT(arr_idx < DUK_HOBJECT_GET_ASIZE(obj));
59022 		tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, arr_idx);
59023 		tv2 = duk_require_tval(thr, -1);
59024 
59025 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
59026 
59027 		duk_pop_unsafe(thr);  /* [ ...val ] -> [ ... ] */
59028 		return;
59029 	}
59030 
59031 	DUK_DDD(DUK_DDDPRINT("define property fast path didn't work, use slow path"));
59032 
59033 	key = duk_push_uint_to_hstring(thr, (duk_uint_t) arr_idx);
59034 	DUK_ASSERT(key != NULL);
59035 	duk_insert(thr, -2);  /* [ ... val key ] -> [ ... key val ] */
59036 
59037 	duk_hobject_define_property_internal(thr, obj, key, flags);
59038 
59039 	duk_pop_unsafe(thr);  /* [ ... key ] -> [ ... ] */
59040 }
59041 
59042 /*
59043  *  Internal helpers for managing object 'length'
59044  */
59045 
59046 DUK_INTERNAL duk_size_t duk_hobject_get_length(duk_hthread *thr, duk_hobject *obj) {
59047 	duk_double_t val;
59048 
59049 	DUK_ASSERT_CTX_VALID(thr);
59050 	DUK_ASSERT(obj != NULL);
59051 
59052 	/* Fast path for Arrays. */
59053 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59054 		return ((duk_harray *) obj)->length;
59055 	}
59056 
59057 	/* Slow path, .length can be e.g. accessor, obj can be a Proxy, etc. */
59058 	duk_push_hobject(thr, obj);
59059 	duk_push_hstring_stridx(thr, DUK_STRIDX_LENGTH);
59060 	(void) duk_hobject_getprop(thr,
59061 	                           DUK_GET_TVAL_NEGIDX(thr, -2),
59062 	                           DUK_GET_TVAL_NEGIDX(thr, -1));
59063 	val = duk_to_number_m1(thr);
59064 	duk_pop_3_unsafe(thr);
59065 
59066 	/* This isn't part of ECMAScript semantics; return a value within
59067 	 * duk_size_t range, or 0 otherwise.
59068 	 */
59069 	if (val >= 0.0 && val <= (duk_double_t) DUK_SIZE_MAX) {
59070 		return (duk_size_t) val;
59071 	}
59072 	return 0;
59073 }
59074 
59075 /*
59076  *  Fast finalizer check for an object.  Walks the prototype chain, checking
59077  *  for finalizer presence using DUK_HOBJECT_FLAG_HAVE_FINALIZER which is kept
59078  *  in sync with the actual property when setting/removing the finalizer.
59079  */
59080 
59081 #if defined(DUK_USE_HEAPPTR16)
59082 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_heap *heap, duk_hobject *obj) {
59083 #else
59084 DUK_INTERNAL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj) {
59085 #endif
59086 	duk_uint_t sanity;
59087 
59088 	DUK_ASSERT(obj != NULL);
59089 
59090 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
59091 	do {
59092 		if (DUK_UNLIKELY(DUK_HOBJECT_HAS_HAVE_FINALIZER(obj))) {
59093 			return 1;
59094 		}
59095 		if (DUK_UNLIKELY(sanity-- == 0)) {
59096 			DUK_D(DUK_DPRINT("prototype loop when checking for finalizer existence; returning false"));
59097 			return 0;
59098 		}
59099 #if defined(DUK_USE_HEAPPTR16)
59100 		DUK_ASSERT(heap != NULL);
59101 		obj = DUK_HOBJECT_GET_PROTOTYPE(heap, obj);
59102 #else
59103 		obj = DUK_HOBJECT_GET_PROTOTYPE(NULL, obj);  /* 'heap' arg ignored */
59104 #endif
59105 	} while (obj != NULL);
59106 
59107 	return 0;
59108 }
59109 
59110 /*
59111  *  Object.getOwnPropertyDescriptor()  (E5 Sections 15.2.3.3, 8.10.4)
59112  *
59113  *  [ ... key ] -> [ ... desc/undefined ]
59114  */
59115 
59116 DUK_INTERNAL void duk_hobject_object_get_own_property_descriptor(duk_hthread *thr, duk_idx_t obj_idx) {
59117 	duk_hobject *obj;
59118 	duk_hstring *key;
59119 	duk_propdesc pd;
59120 
59121 	DUK_ASSERT(thr != NULL);
59122 	DUK_ASSERT(thr->heap != NULL);
59123 
59124 	obj = duk_require_hobject_promote_mask(thr, obj_idx, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
59125 	key = duk_to_property_key_hstring(thr, -1);
59126 	DUK_ASSERT(key != NULL);
59127 
59128 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59129 
59130 	if (!duk_hobject_get_own_propdesc(thr, obj, key, &pd, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59131 		duk_push_undefined(thr);
59132 		duk_remove_m2(thr);
59133 		return;
59134 	}
59135 
59136 	duk_push_object(thr);
59137 
59138 	/* [ ... key value desc ] */
59139 
59140 	if (DUK_PROPDESC_IS_ACCESSOR(&pd)) {
59141 		/* If a setter/getter is missing (undefined), the descriptor must
59142 		 * still have the property present with the value 'undefined'.
59143 		 */
59144 		if (pd.get) {
59145 			duk_push_hobject(thr, pd.get);
59146 		} else {
59147 			duk_push_undefined(thr);
59148 		}
59149 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_GET);
59150 		if (pd.set) {
59151 			duk_push_hobject(thr, pd.set);
59152 		} else {
59153 			duk_push_undefined(thr);
59154 		}
59155 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_SET);
59156 	} else {
59157 		duk_dup_m2(thr);
59158 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_VALUE);
59159 		duk_push_boolean(thr, DUK_PROPDESC_IS_WRITABLE(&pd));
59160 		duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_WRITABLE);
59161 	}
59162 	duk_push_boolean(thr, DUK_PROPDESC_IS_ENUMERABLE(&pd));
59163 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_ENUMERABLE);
59164 	duk_push_boolean(thr, DUK_PROPDESC_IS_CONFIGURABLE(&pd));
59165 	duk_put_prop_stridx_short(thr, -2, DUK_STRIDX_CONFIGURABLE);
59166 
59167 	/* [ ... key value desc ] */
59168 
59169 	duk_replace(thr, -3);
59170 	duk_pop_unsafe(thr);  /* -> [ ... desc ] */
59171 }
59172 
59173 /*
59174  *  NormalizePropertyDescriptor() related helper.
59175  *
59176  *  Internal helper which validates and normalizes a property descriptor
59177  *  represented as an ECMAScript object (e.g. argument to defineProperty()).
59178  *  The output of this conversion is a set of defprop_flags and possibly
59179  *  some values pushed on the value stack to (1) ensure borrowed pointers
59180  *  remain valid, and (2) avoid unnecessary pops for footprint reasons.
59181  *  Caller must manage stack top carefully because the number of values
59182  *  pushed depends on the input property descriptor.
59183  *
59184  *  The original descriptor object must not be altered in the process.
59185  */
59186 
59187 /* XXX: very basic optimization -> duk_get_prop_stridx_top */
59188 
59189 DUK_INTERNAL
59190 void duk_hobject_prepare_property_descriptor(duk_hthread *thr,
59191                                              duk_idx_t idx_in,
59192                                              duk_uint_t *out_defprop_flags,
59193                                              duk_idx_t *out_idx_value,
59194                                              duk_hobject **out_getter,
59195                                              duk_hobject **out_setter) {
59196 	duk_idx_t idx_value = -1;
59197 	duk_hobject *getter = NULL;
59198 	duk_hobject *setter = NULL;
59199 	duk_bool_t is_data_desc = 0;
59200 	duk_bool_t is_acc_desc = 0;
59201 	duk_uint_t defprop_flags = 0;
59202 
59203 	DUK_ASSERT(out_defprop_flags != NULL);
59204 	DUK_ASSERT(out_idx_value != NULL);
59205 	DUK_ASSERT(out_getter != NULL);
59206 	DUK_ASSERT(out_setter != NULL);
59207 	DUK_ASSERT(idx_in <= 0x7fffL);  /* short variants would be OK, but not used to avoid shifts */
59208 
59209 	/* Must be an object, otherwise TypeError (E5.1 Section 8.10.5, step 1). */
59210 	idx_in = duk_require_normalize_index(thr, idx_in);
59211 	(void) duk_require_hobject(thr, idx_in);
59212 
59213 	/* The coercion order must match the ToPropertyDescriptor() algorithm
59214 	 * so that side effects in coercion happen in the correct order.
59215 	 * (This order also happens to be compatible with duk_def_prop(),
59216 	 * although it doesn't matter in practice.)
59217 	 */
59218 
59219 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_VALUE)) {
59220 		is_data_desc = 1;
59221 		defprop_flags |= DUK_DEFPROP_HAVE_VALUE;
59222 		idx_value = duk_get_top_index(thr);
59223 	}
59224 
59225 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_WRITABLE)) {
59226 		is_data_desc = 1;
59227 		if (duk_to_boolean_top_pop(thr)) {
59228 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE | DUK_DEFPROP_WRITABLE;
59229 		} else {
59230 			defprop_flags |= DUK_DEFPROP_HAVE_WRITABLE;
59231 		}
59232 	}
59233 
59234 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_GET)) {
59235 		duk_tval *tv = duk_require_tval(thr, -1);
59236 		duk_hobject *h_get;
59237 
59238 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59239 			/* undefined is accepted */
59240 			DUK_ASSERT(getter == NULL);
59241 		} else {
59242 			/* NOTE: lightfuncs are coerced to full functions because
59243 			 * lightfuncs don't fit into a property value slot.  This
59244 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59245 			 */
59246 			h_get = duk_get_hobject_promote_lfunc(thr, -1);
59247 			if (h_get == NULL || !DUK_HOBJECT_IS_CALLABLE(h_get)) {
59248 				goto type_error;
59249 			}
59250 			getter = h_get;
59251 		}
59252 		is_acc_desc = 1;
59253 		defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
59254 	}
59255 
59256 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_SET)) {
59257 		duk_tval *tv = duk_require_tval(thr, -1);
59258 		duk_hobject *h_set;
59259 
59260 		if (DUK_TVAL_IS_UNDEFINED(tv)) {
59261 			/* undefined is accepted */
59262 			DUK_ASSERT(setter == NULL);
59263 		}  else {
59264 			/* NOTE: lightfuncs are coerced to full functions because
59265 			 * lightfuncs don't fit into a property value slot.  This
59266 			 * has some side effects, see test-dev-lightfunc-accessor.js.
59267 			 */
59268 			h_set = duk_get_hobject_promote_lfunc(thr, -1);
59269 			if (h_set == NULL || !DUK_HOBJECT_IS_CALLABLE(h_set)) {
59270 				goto type_error;
59271 			}
59272 			setter = h_set;
59273 		}
59274 		is_acc_desc = 1;
59275 		defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
59276 	}
59277 
59278 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_ENUMERABLE)) {
59279 		if (duk_to_boolean_top_pop(thr)) {
59280 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_ENUMERABLE;
59281 		} else {
59282 			defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE;
59283 		}
59284 	}
59285 
59286 	if (duk_get_prop_stridx(thr, idx_in, DUK_STRIDX_CONFIGURABLE)) {
59287 		if (duk_to_boolean_top_pop(thr)) {
59288 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE | DUK_DEFPROP_CONFIGURABLE;
59289 		} else {
59290 			defprop_flags |= DUK_DEFPROP_HAVE_CONFIGURABLE;
59291 		}
59292 	}
59293 
59294 	if (is_data_desc && is_acc_desc) {
59295 		goto type_error;
59296 	}
59297 
59298 	*out_defprop_flags = defprop_flags;
59299 	*out_idx_value = idx_value;
59300 	*out_getter = getter;
59301 	*out_setter = setter;
59302 
59303 	/* [ ... [multiple values] ] */
59304 	return;
59305 
59306  type_error:
59307 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_DESCRIPTOR);
59308 	DUK_WO_NORETURN(return;);
59309 }
59310 
59311 /*
59312  *  Object.defineProperty() related helper (E5 Section 15.2.3.6).
59313  *  Also handles ES2015 Reflect.defineProperty().
59314  *
59315  *  Inlines all [[DefineOwnProperty]] exotic behaviors.
59316  *
59317  *  Note: ECMAScript compliant [[DefineOwnProperty]](P, Desc, Throw) is not
59318  *  implemented directly, but Object.defineProperty() serves its purpose.
59319  *  We don't need the [[DefineOwnProperty]] internally and we don't have a
59320  *  property descriptor with 'missing values' so it's easier to avoid it
59321  *  entirely.
59322  *
59323  *  Note: this is only called for actual objects, not primitive values.
59324  *  This must support virtual properties for full objects (e.g. Strings)
59325  *  but not for plain values (e.g. strings).  Lightfuncs, even though
59326  *  primitive in a sense, are treated like objects and accepted as target
59327  *  values.
59328  */
59329 
59330 /* XXX: this is a major target for size optimization */
59331 DUK_INTERNAL
59332 duk_bool_t duk_hobject_define_property_helper(duk_hthread *thr,
59333                                               duk_uint_t defprop_flags,
59334                                               duk_hobject *obj,
59335                                               duk_hstring *key,
59336                                               duk_idx_t idx_value,
59337                                               duk_hobject *get,
59338                                               duk_hobject *set,
59339                                               duk_bool_t throw_flag) {
59340 	duk_uint32_t arr_idx;
59341 	duk_tval tv;
59342 	duk_bool_t has_enumerable;
59343 	duk_bool_t has_configurable;
59344 	duk_bool_t has_writable;
59345 	duk_bool_t has_value;
59346 	duk_bool_t has_get;
59347 	duk_bool_t has_set;
59348 	duk_bool_t is_enumerable;
59349 	duk_bool_t is_configurable;
59350 	duk_bool_t is_writable;
59351 	duk_bool_t force_flag;
59352 	duk_small_uint_t new_flags;
59353 	duk_propdesc curr;
59354 	duk_uint32_t arridx_new_array_length;  /* != 0 => post-update for array 'length' (used when key is an array index) */
59355 	duk_uint32_t arrlen_old_len;
59356 	duk_uint32_t arrlen_new_len;
59357 	duk_bool_t pending_write_protect;
59358 
59359 	DUK_ASSERT(thr != NULL);
59360 	DUK_ASSERT(thr->heap != NULL);
59361 	DUK_ASSERT(obj != NULL);
59362 	DUK_ASSERT(key != NULL);
59363 	/* idx_value may be < 0 (no value), set and get may be NULL */
59364 
59365 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
59366 
59367 	/* All the flags fit in 16 bits, so will fit into duk_bool_t. */
59368 
59369 	has_writable = (defprop_flags & DUK_DEFPROP_HAVE_WRITABLE);
59370 	has_enumerable = (defprop_flags & DUK_DEFPROP_HAVE_ENUMERABLE);
59371 	has_configurable = (defprop_flags & DUK_DEFPROP_HAVE_CONFIGURABLE);
59372 	has_value = (defprop_flags & DUK_DEFPROP_HAVE_VALUE);
59373 	has_get = (defprop_flags & DUK_DEFPROP_HAVE_GETTER);
59374 	has_set = (defprop_flags & DUK_DEFPROP_HAVE_SETTER);
59375 	is_writable = (defprop_flags & DUK_DEFPROP_WRITABLE);
59376 	is_enumerable = (defprop_flags & DUK_DEFPROP_ENUMERABLE);
59377 	is_configurable = (defprop_flags & DUK_DEFPROP_CONFIGURABLE);
59378 	force_flag = (defprop_flags & DUK_DEFPROP_FORCE);
59379 
59380 	arr_idx = DUK_HSTRING_GET_ARRIDX_SLOW(key);
59381 
59382 	arridx_new_array_length = 0;
59383 	pending_write_protect = 0;
59384 	arrlen_old_len = 0;
59385 	arrlen_new_len = 0;
59386 
59387 	DUK_DDD(DUK_DDDPRINT("has_enumerable=%ld is_enumerable=%ld "
59388 	                     "has_configurable=%ld is_configurable=%ld "
59389 	                     "has_writable=%ld is_writable=%ld "
59390 	                     "has_value=%ld value=%!T "
59391 	                     "has_get=%ld get=%p=%!O "
59392 	                     "has_set=%ld set=%p=%!O "
59393 	                     "arr_idx=%ld throw_flag=!%ld",
59394 	                     (long) has_enumerable, (long) is_enumerable,
59395 	                     (long) has_configurable, (long) is_configurable,
59396 	                     (long) has_writable, (long) is_writable,
59397 	                     (long) has_value, (duk_tval *) (idx_value >= 0 ? duk_get_tval(thr, idx_value) : NULL),
59398 	                     (long) has_get, (void *) get, (duk_heaphdr *) get,
59399 	                     (long) has_set, (void *) set, (duk_heaphdr *) set,
59400 	                     (long) arr_idx, (long) throw_flag));
59401 
59402 	/*
59403 	 *  Array exotic behaviors can be implemented at this point.  The local variables
59404 	 *  are essentially a 'value copy' of the input descriptor (Desc), which is modified
59405 	 *  by the Array [[DefineOwnProperty]] (E5 Section 15.4.5.1).
59406 	 */
59407 
59408 	if (!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59409 		goto skip_array_exotic;
59410 	}
59411 
59412 	if (key == DUK_HTHREAD_STRING_LENGTH(thr)) {
59413 		duk_harray *a;
59414 
59415 		/* E5 Section 15.4.5.1, step 3, steps a - i are implemented here, j - n at the end */
59416 		if (!has_value) {
59417 			DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', but no value in descriptor -> normal behavior"));
59418 			goto skip_array_exotic;
59419 		}
59420 
59421 		DUK_DDD(DUK_DDDPRINT("exotic array behavior for 'length', value present in descriptor -> exotic behavior"));
59422 
59423 		/*
59424 		 *  Get old and new length
59425 		 */
59426 
59427 		a = (duk_harray *) obj;
59428 		DUK_ASSERT_HARRAY_VALID(a);
59429 		arrlen_old_len = a->length;
59430 
59431 		DUK_ASSERT(idx_value >= 0);
59432 		arrlen_new_len = duk__to_new_array_length_checked(thr, DUK_GET_TVAL_POSIDX(thr, idx_value));
59433 		duk_push_u32(thr, arrlen_new_len);
59434 		duk_replace(thr, idx_value);  /* step 3.e: replace 'Desc.[[Value]]' */
59435 
59436 		DUK_DDD(DUK_DDDPRINT("old_len=%ld, new_len=%ld", (long) arrlen_old_len, (long) arrlen_new_len));
59437 
59438 		if (arrlen_new_len >= arrlen_old_len) {
59439 			/* standard behavior, step 3.f.i */
59440 			DUK_DDD(DUK_DDDPRINT("new length is same or higher as previous => standard behavior"));
59441 			goto skip_array_exotic;
59442 		}
59443 		DUK_DDD(DUK_DDDPRINT("new length is smaller than previous => exotic post behavior"));
59444 
59445 		/* XXX: consolidated algorithm step 15.f -> redundant? */
59446 		if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
59447 			/* Array .length is always non-configurable; if it's also
59448 			 * non-writable, don't allow it to be written.
59449 			 */
59450 			goto fail_not_configurable;
59451 		}
59452 
59453 		/* steps 3.h and 3.i */
59454 		if (has_writable && !is_writable) {
59455 			DUK_DDD(DUK_DDDPRINT("desc writable is false, force it back to true, and flag pending write protect"));
59456 			is_writable = 1;
59457 			pending_write_protect = 1;
59458 		}
59459 
59460 		/* remaining actual steps are carried out if standard DefineOwnProperty succeeds */
59461 	} else if (arr_idx != DUK__NO_ARRAY_INDEX) {
59462 		/* XXX: any chance of unifying this with the 'length' key handling? */
59463 
59464 		/* E5 Section 15.4.5.1, step 4 */
59465 		duk_uint32_t old_len;
59466 		duk_harray *a;
59467 
59468 		a = (duk_harray *) obj;
59469 		DUK_ASSERT_HARRAY_VALID(a);
59470 
59471 		old_len = a->length;
59472 
59473 		if (arr_idx >= old_len) {
59474 			DUK_DDD(DUK_DDDPRINT("defineProperty requires array length update "
59475 			                     "(arr_idx=%ld, old_len=%ld)",
59476 			                     (long) arr_idx, (long) old_len));
59477 
59478 			if (DUK_HARRAY_LENGTH_NONWRITABLE(a) && !force_flag) {
59479 				/* Array .length is always non-configurable, so
59480 				 * if it's also non-writable, don't allow a value
59481 				 * write.  With force flag allow writing.
59482 				 */
59483 				goto fail_not_configurable;
59484 			}
59485 
59486 			/* actual update happens once write has been completed without
59487 			 * error below.
59488 			 */
59489 			DUK_ASSERT(arr_idx != 0xffffffffUL);
59490 			arridx_new_array_length = arr_idx + 1;
59491 		} else {
59492 			DUK_DDD(DUK_DDDPRINT("defineProperty does not require length update "
59493 			                     "(arr_idx=%ld, old_len=%ld) -> standard behavior",
59494 			                     (long) arr_idx, (long) old_len));
59495 		}
59496 	}
59497  skip_array_exotic:
59498 
59499 	/* XXX: There is currently no support for writing buffer object
59500 	 * indexed elements here.  Attempt to do so will succeed and
59501 	 * write a concrete property into the buffer object.  This should
59502 	 * be fixed at some point but because buffers are a custom feature
59503 	 * anyway, this is relatively unimportant.
59504 	 */
59505 
59506 	/*
59507 	 *  Actual Object.defineProperty() default algorithm.
59508 	 */
59509 
59510 	/*
59511 	 *  First check whether property exists; if not, simple case.  This covers
59512 	 *  steps 1-4.
59513 	 */
59514 
59515 	if (!duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE)) {
59516 		DUK_DDD(DUK_DDDPRINT("property does not exist"));
59517 
59518 		if (!DUK_HOBJECT_HAS_EXTENSIBLE(obj) && !force_flag) {
59519 			goto fail_not_extensible;
59520 		}
59521 
59522 #if defined(DUK_USE_ROM_OBJECTS)
59523 		/* ROM objects are never extensible but force flag may
59524 		 * allow us to come here anyway.
59525 		 */
59526 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj) || !DUK_HOBJECT_HAS_EXTENSIBLE(obj));
59527 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
59528 			DUK_D(DUK_DPRINT("attempt to define property on a read-only target object"));
59529 			goto fail_not_configurable;
59530 		}
59531 #endif
59532 
59533 		/* XXX: share final setting code for value and flags?  difficult because
59534 		 * refcount code is different.  Share entry allocation?  But can't allocate
59535 		 * until array index checked.
59536 		 */
59537 
59538 		/* steps 4.a and 4.b are tricky */
59539 		if (has_set || has_get) {
59540 			duk_int_t e_idx;
59541 
59542 			DUK_DDD(DUK_DDDPRINT("create new accessor property"));
59543 
59544 			DUK_ASSERT(has_set || set == NULL);
59545 			DUK_ASSERT(has_get || get == NULL);
59546 			DUK_ASSERT(!has_value);
59547 			DUK_ASSERT(!has_writable);
59548 
59549 			new_flags = DUK_PROPDESC_FLAG_ACCESSOR;  /* defaults, E5 Section 8.6.1, Table 7 */
59550 			if (has_enumerable && is_enumerable) {
59551 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59552 			}
59553 			if (has_configurable && is_configurable) {
59554 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59555 			}
59556 
59557 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59558 				DUK_DDD(DUK_DDDPRINT("accessor cannot go to array part, abandon array"));
59559 				duk__abandon_array_checked(thr, obj);
59560 			}
59561 
59562 			/* write to entry part */
59563 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
59564 			DUK_ASSERT(e_idx >= 0);
59565 
59566 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, e_idx, get);
59567 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, e_idx, set);
59568 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
59569 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
59570 
59571 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
59572 			goto success_exotics;
59573 		} else {
59574 			duk_int_t e_idx;
59575 			duk_tval *tv2;
59576 
59577 			DUK_DDD(DUK_DDDPRINT("create new data property"));
59578 
59579 			DUK_ASSERT(!has_set);
59580 			DUK_ASSERT(!has_get);
59581 
59582 			new_flags = 0;  /* defaults, E5 Section 8.6.1, Table 7 */
59583 			if (has_writable && is_writable) {
59584 				new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
59585 			}
59586 			if (has_enumerable && is_enumerable) {
59587 				new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59588 			}
59589 			if (has_configurable && is_configurable) {
59590 				new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59591 			}
59592 			if (has_value) {
59593 				duk_tval *tv_tmp = duk_require_tval(thr, idx_value);
59594 				DUK_TVAL_SET_TVAL(&tv, tv_tmp);
59595 			} else {
59596 				DUK_TVAL_SET_UNDEFINED(&tv);  /* default value */
59597 			}
59598 
59599 			if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_ARRAY_PART(obj)) {
59600 				if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
59601 #if 0
59602 					DUK_DDD(DUK_DDDPRINT("new data property attributes match array defaults, attempt to write to array part"));
59603 					/* may become sparse...*/
59604 #endif
59605 					/* XXX: handling for array part missing now; this doesn't affect
59606 					 * compliance but causes array entry writes using defineProperty()
59607 					 * to always abandon array part.
59608 					 */
59609 				}
59610 				DUK_DDD(DUK_DDDPRINT("new data property cannot go to array part, abandon array"));
59611 				duk__abandon_array_checked(thr, obj);
59612 				/* fall through */
59613 			}
59614 
59615 			/* write to entry part */
59616 			e_idx = duk__hobject_alloc_entry_checked(thr, obj, key);
59617 			DUK_ASSERT(e_idx >= 0);
59618 			tv2 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, e_idx);
59619 			DUK_TVAL_SET_TVAL(tv2, &tv);
59620 			DUK_TVAL_INCREF(thr, tv2);
59621 
59622 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, e_idx, new_flags);
59623 			goto success_exotics;
59624 		}
59625 		DUK_UNREACHABLE();
59626 	}
59627 
59628 	/* we currently assume virtual properties are not configurable (as none of them are) */
59629 	DUK_ASSERT((curr.e_idx >= 0 || curr.a_idx >= 0) || !(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE));
59630 
59631 	/* [obj key desc value get set curr_value] */
59632 
59633 	/*
59634 	 *  Property already exists.  Steps 5-6 detect whether any changes need
59635 	 *  to be made.
59636 	 */
59637 
59638 	if (has_enumerable) {
59639 		if (is_enumerable) {
59640 			if (!(curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE)) {
59641 				goto need_check;
59642 			}
59643 		} else {
59644 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
59645 				goto need_check;
59646 			}
59647 		}
59648 	}
59649 	if (has_configurable) {
59650 		if (is_configurable) {
59651 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
59652 				goto need_check;
59653 			}
59654 		} else {
59655 			if (curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
59656 				goto need_check;
59657 			}
59658 		}
59659 	}
59660 	if (has_value) {
59661 		duk_tval *tmp1;
59662 		duk_tval *tmp2;
59663 
59664 		/* attempt to change from accessor to data property */
59665 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59666 			goto need_check;
59667 		}
59668 
59669 		tmp1 = duk_require_tval(thr, -1);         /* curr value */
59670 		tmp2 = duk_require_tval(thr, idx_value);  /* new value */
59671 		if (!duk_js_samevalue(tmp1, tmp2)) {
59672 			goto need_check;
59673 		}
59674 	}
59675 	if (has_writable) {
59676 		/* attempt to change from accessor to data property */
59677 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59678 			goto need_check;
59679 		}
59680 
59681 		if (is_writable) {
59682 			if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE)) {
59683 				goto need_check;
59684 			}
59685 		} else {
59686 			if (curr.flags & DUK_PROPDESC_FLAG_WRITABLE) {
59687 				goto need_check;
59688 			}
59689 		}
59690 	}
59691 	if (has_set) {
59692 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59693 			if (set != curr.set) {
59694 				goto need_check;
59695 			}
59696 		} else {
59697 			goto need_check;
59698 		}
59699 	}
59700 	if (has_get) {
59701 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59702 			if (get != curr.get) {
59703 				goto need_check;
59704 			}
59705 		} else {
59706 			goto need_check;
59707 		}
59708 	}
59709 
59710 	/* property exists, either 'desc' is empty, or all values
59711 	 * match (SameValue)
59712 	 */
59713 	goto success_no_exotics;
59714 
59715  need_check:
59716 
59717 	/*
59718 	 *  Some change(s) need to be made.  Steps 7-11.
59719 	 */
59720 
59721 	/* shared checks for all descriptor types */
59722 	if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59723 		if (has_configurable && is_configurable) {
59724 			goto fail_not_configurable;
59725 		}
59726 		if (has_enumerable) {
59727 			if (curr.flags & DUK_PROPDESC_FLAG_ENUMERABLE) {
59728 				if (!is_enumerable) {
59729 					goto fail_not_configurable;
59730 				}
59731 			} else {
59732 				if (is_enumerable) {
59733 					goto fail_not_configurable;
59734 				}
59735 			}
59736 		}
59737 	}
59738 
59739 	/* Virtual properties don't have backing so they can't mostly be
59740 	 * edited.  Some virtual properties are, however, writable: for
59741 	 * example, virtual index properties of buffer objects and Array
59742 	 * instance .length.  These are not configurable so the checks
59743 	 * above mostly cover attempts to change them, except when the
59744 	 * duk_def_prop() call is used with DUK_DEFPROP_FORCE; even in
59745 	 * that case we can't forcibly change the property attributes
59746 	 * because they don't have concrete backing.
59747 	 */
59748 
59749 	/* XXX: for ROM objects too it'd be best if value modify was
59750 	 * allowed if the value matches SameValue.
59751 	 */
59752 	/* Reject attempt to change a read-only object. */
59753 #if defined(DUK_USE_ROM_OBJECTS)
59754 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
59755 		DUK_DD(DUK_DDPRINT("attempt to define property on read-only target object"));
59756 		goto fail_not_configurable;
59757 	}
59758 #endif
59759 
59760 	/* descriptor type specific checks */
59761 	if (has_set || has_get) {
59762 		/* IsAccessorDescriptor(desc) == true */
59763 		DUK_ASSERT(!has_writable);
59764 		DUK_ASSERT(!has_value);
59765 
59766 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59767 			/* curr and desc are accessors */
59768 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59769 				if (has_set && set != curr.set) {
59770 					goto fail_not_configurable;
59771 				}
59772 				if (has_get && get != curr.get) {
59773 					goto fail_not_configurable;
59774 				}
59775 			}
59776 		} else {
59777 			duk_bool_t rc;
59778 			duk_tval *tv1;
59779 
59780 			/* curr is data, desc is accessor */
59781 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59782 				goto fail_not_configurable;
59783 			}
59784 
59785 			DUK_DDD(DUK_DDDPRINT("convert property to accessor property"));
59786 			if (curr.a_idx >= 0) {
59787 				DUK_DDD(DUK_DDDPRINT("property to convert is stored in an array entry, abandon array and re-lookup"));
59788 				duk__abandon_array_checked(thr, obj);
59789 				duk_pop_unsafe(thr);  /* remove old value */
59790 				rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
59791 				DUK_UNREF(rc);
59792 				DUK_ASSERT(rc != 0);
59793 				DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
59794 			}
59795 			if (curr.e_idx < 0) {
59796 				DUK_ASSERT(curr.a_idx < 0 && curr.e_idx < 0);
59797 				goto fail_virtual;  /* safeguard for virtual property */
59798 			}
59799 
59800 			DUK_ASSERT(curr.e_idx >= 0);
59801 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
59802 
59803 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
59804 			DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, tv1);  /* XXX: just decref */
59805 
59806 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
59807 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
59808 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
59809 			DUK_HOBJECT_E_SLOT_SET_ACCESSOR(thr->heap, obj, curr.e_idx);
59810 
59811 			DUK_DDD(DUK_DDDPRINT("flags after data->accessor conversion: 0x%02lx",
59812 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
59813 			/* Update curr.flags; faster than a re-lookup. */
59814 			curr.flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
59815 			curr.flags |= DUK_PROPDESC_FLAG_ACCESSOR;
59816 		}
59817 	} else if (has_value || has_writable) {
59818 		/* IsDataDescriptor(desc) == true */
59819 		DUK_ASSERT(!has_set);
59820 		DUK_ASSERT(!has_get);
59821 
59822 		if (curr.flags & DUK_PROPDESC_FLAG_ACCESSOR) {
59823 			duk_hobject *tmp;
59824 
59825 			/* curr is accessor, desc is data */
59826 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59827 				goto fail_not_configurable;
59828 			}
59829 
59830 			/* curr is accessor -> cannot be in array part. */
59831 			DUK_ASSERT(curr.a_idx < 0);
59832 			if (curr.e_idx < 0) {
59833 				goto fail_virtual;  /* safeguard; no virtual accessors now */
59834 			}
59835 
59836 			DUK_DDD(DUK_DDDPRINT("convert property to data property"));
59837 
59838 			DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
59839 			tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
59840 			DUK_UNREF(tmp);
59841 			DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, NULL);
59842 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59843 			tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
59844 			DUK_UNREF(tmp);
59845 			DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, NULL);
59846 			DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
59847 
59848 			DUK_TVAL_SET_UNDEFINED(DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx));
59849 			DUK_HOBJECT_E_SLOT_CLEAR_WRITABLE(thr->heap, obj, curr.e_idx);
59850 			DUK_HOBJECT_E_SLOT_CLEAR_ACCESSOR(thr->heap, obj, curr.e_idx);
59851 
59852 			DUK_DDD(DUK_DDDPRINT("flags after accessor->data conversion: 0x%02lx",
59853 			                     (unsigned long) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, curr.e_idx)));
59854 
59855 			/* Update curr.flags; faster than a re-lookup. */
59856 			curr.flags &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_ACCESSOR);
59857 		} else {
59858 			/* curr and desc are data */
59859 			if (!(curr.flags & DUK_PROPDESC_FLAG_CONFIGURABLE) && !force_flag) {
59860 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_writable && is_writable) {
59861 					goto fail_not_configurable;
59862 				}
59863 				/* Note: changing from writable to non-writable is OK */
59864 				if (!(curr.flags & DUK_PROPDESC_FLAG_WRITABLE) && has_value) {
59865 					duk_tval *tmp1 = duk_require_tval(thr, -1);         /* curr value */
59866 					duk_tval *tmp2 = duk_require_tval(thr, idx_value);  /* new value */
59867 					if (!duk_js_samevalue(tmp1, tmp2)) {
59868 						goto fail_not_configurable;
59869 					}
59870 				}
59871 			}
59872 		}
59873 	} else {
59874 		/* IsGenericDescriptor(desc) == true; this means in practice that 'desc'
59875 		 * only has [[Enumerable]] or [[Configurable]] flag updates, which are
59876 		 * allowed at this point.
59877 		 */
59878 
59879 		DUK_ASSERT(!has_value && !has_writable && !has_get && !has_set);
59880 	}
59881 
59882 	/*
59883 	 *  Start doing property attributes updates.  Steps 12-13.
59884 	 *
59885 	 *  Start by computing new attribute flags without writing yet.
59886 	 *  Property type conversion is done above if necessary.
59887 	 */
59888 
59889 	new_flags = curr.flags;
59890 
59891 	if (has_enumerable) {
59892 		if (is_enumerable) {
59893 			new_flags |= DUK_PROPDESC_FLAG_ENUMERABLE;
59894 		} else {
59895 			new_flags &= ~DUK_PROPDESC_FLAG_ENUMERABLE;
59896 		}
59897 	}
59898 	if (has_configurable) {
59899 		if (is_configurable) {
59900 			new_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
59901 		} else {
59902 			new_flags &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
59903 		}
59904 	}
59905 	if (has_writable) {
59906 		if (is_writable) {
59907 			new_flags |= DUK_PROPDESC_FLAG_WRITABLE;
59908 		} else {
59909 			new_flags &= ~DUK_PROPDESC_FLAG_WRITABLE;
59910 		}
59911 	}
59912 
59913 	/* XXX: write protect after flag? -> any chance of handling it here? */
59914 
59915 	DUK_DDD(DUK_DDDPRINT("new flags that we want to write: 0x%02lx",
59916 	                     (unsigned long) new_flags));
59917 
59918 	/*
59919 	 *  Check whether we need to abandon an array part (if it exists)
59920 	 */
59921 
59922 	if (curr.a_idx >= 0) {
59923 		duk_bool_t rc;
59924 
59925 		DUK_ASSERT(curr.e_idx < 0);
59926 
59927 		if (new_flags == DUK_PROPDESC_FLAGS_WEC) {
59928 			duk_tval *tv1, *tv2;
59929 
59930 			DUK_DDD(DUK_DDDPRINT("array index, new property attributes match array defaults, update in-place"));
59931 
59932 			DUK_ASSERT(curr.flags == DUK_PROPDESC_FLAGS_WEC);  /* must have been, since in array part */
59933 			DUK_ASSERT(!has_set);
59934 			DUK_ASSERT(!has_get);
59935 			DUK_ASSERT(idx_value >= 0);  /* must be: if attributes match and we get here the value must differ (otherwise no change) */
59936 
59937 			tv2 = duk_require_tval(thr, idx_value);
59938 			tv1 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, curr.a_idx);
59939 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate a_idx */
59940 			goto success_exotics;
59941 		}
59942 
59943 		DUK_DDD(DUK_DDDPRINT("array index, new property attributes do not match array defaults, abandon array and re-lookup"));
59944 		duk__abandon_array_checked(thr, obj);
59945 		duk_pop_unsafe(thr);  /* remove old value */
59946 		rc = duk__get_own_propdesc_raw(thr, obj, key, arr_idx, &curr, DUK_GETDESC_FLAG_PUSH_VALUE);
59947 		DUK_UNREF(rc);
59948 		DUK_ASSERT(rc != 0);
59949 		DUK_ASSERT(curr.e_idx >= 0 && curr.a_idx < 0);
59950 	}
59951 
59952 	DUK_DDD(DUK_DDDPRINT("updating existing property in entry part"));
59953 
59954 	/* Array case is handled comprehensively above: either in entry
59955 	 * part or a virtual property.
59956 	 */
59957 	DUK_ASSERT(curr.a_idx < 0);
59958 
59959 	DUK_DDD(DUK_DDDPRINT("update existing property attributes"));
59960 	if (curr.e_idx >= 0) {
59961 		DUK_HOBJECT_E_SET_FLAGS(thr->heap, obj, curr.e_idx, new_flags);
59962 	} else {
59963 		/* For Array .length the only allowed transition is for .length
59964 		 * to become non-writable.
59965 		 */
59966 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
59967 			duk_harray *a;
59968 			a = (duk_harray *) obj;
59969 			DUK_DD(DUK_DDPRINT("Object.defineProperty() attribute update for duk_harray .length -> %02lx", (unsigned long) new_flags));
59970 			DUK_ASSERT_HARRAY_VALID(a);
59971 			if ((new_flags & DUK_PROPDESC_FLAGS_EC) != (curr.flags & DUK_PROPDESC_FLAGS_EC)) {
59972 				DUK_D(DUK_DPRINT("Object.defineProperty() attempt to change virtual array .length enumerable or configurable attribute, fail"));
59973 				goto fail_virtual;
59974 			}
59975 			if (new_flags & DUK_PROPDESC_FLAG_WRITABLE) {
59976 				DUK_HARRAY_SET_LENGTH_WRITABLE(a);
59977 			} else {
59978 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
59979 			}
59980 		}
59981 	}
59982 
59983 	if (has_set) {
59984 		duk_hobject *tmp;
59985 
59986 		/* Virtual properties are non-configurable but with a 'force'
59987 		 * flag we might come here so check explicitly for virtual.
59988 		 */
59989 		if (curr.e_idx < 0) {
59990 			goto fail_virtual;
59991 		}
59992 
59993 		DUK_DDD(DUK_DDDPRINT("update existing property setter"));
59994 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
59995 
59996 		tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, obj, curr.e_idx);
59997 		DUK_UNREF(tmp);
59998 		DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, obj, curr.e_idx, set);
59999 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, set);
60000 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60001 	}
60002 	if (has_get) {
60003 		duk_hobject *tmp;
60004 
60005 		if (curr.e_idx < 0) {
60006 			goto fail_virtual;
60007 		}
60008 
60009 		DUK_DDD(DUK_DDDPRINT("update existing property getter"));
60010 		DUK_ASSERT(DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60011 
60012 		tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, obj, curr.e_idx);
60013 		DUK_UNREF(tmp);
60014 		DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, obj, curr.e_idx, get);
60015 		DUK_HOBJECT_INCREF_ALLOWNULL(thr, get);
60016 		DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);  /* side effects; may invalidate e_idx */
60017 	}
60018 	if (has_value) {
60019 		duk_tval *tv1, *tv2;
60020 
60021 		DUK_DDD(DUK_DDDPRINT("update existing property value"));
60022 
60023 		if (curr.e_idx >= 0) {
60024 			DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, obj, curr.e_idx));
60025 			tv2 = duk_require_tval(thr, idx_value);
60026 			tv1 = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, obj, curr.e_idx);
60027 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects; may invalidate e_idx */
60028 		} else {
60029 			DUK_ASSERT(curr.a_idx < 0);  /* array part case handled comprehensively previously */
60030 
60031 			DUK_DD(DUK_DDPRINT("Object.defineProperty(), value update for virtual property"));
60032 			/* XXX: Uint8Array and other typed array virtual writes not currently
60033 			 * handled.
60034 			 */
60035 			if (key == DUK_HTHREAD_STRING_LENGTH(thr) && DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60036 				duk_harray *a;
60037 				a = (duk_harray *) obj;
60038 				DUK_DD(DUK_DDPRINT("Object.defineProperty() value update for duk_harray .length -> %ld", (long) arrlen_new_len));
60039 				DUK_ASSERT_HARRAY_VALID(a);
60040 				a->length = arrlen_new_len;
60041 			} else {
60042 				goto fail_virtual;  /* should not happen */
60043 			}
60044 		}
60045 	}
60046 
60047 	/*
60048 	 *  Standard algorithm succeeded without errors, check for exotic post-behaviors.
60049 	 *
60050 	 *  Arguments exotic behavior in E5 Section 10.6 occurs after the standard
60051 	 *  [[DefineOwnProperty]] has completed successfully.
60052 	 *
60053 	 *  Array exotic behavior in E5 Section 15.4.5.1 is implemented partly
60054 	 *  prior to the default [[DefineOwnProperty]], but:
60055 	 *    - for an array index key (e.g. "10") the final 'length' update occurs here
60056 	 *    - for 'length' key the element deletion and 'length' update occurs here
60057 	 */
60058 
60059  success_exotics:
60060 
60061 	/* curr.a_idx or curr.e_idx may have been invalidated by side effects
60062 	 * above.
60063 	 */
60064 
60065 	/* [obj key desc value get set curr_value] */
60066 
60067 	if (DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj)) {
60068 		duk_harray *a;
60069 
60070 		a = (duk_harray *) obj;
60071 		DUK_ASSERT_HARRAY_VALID(a);
60072 
60073 		if (arridx_new_array_length > 0) {
60074 			/*
60075 			 *  Note: zero works as a "no update" marker because the new length
60076 			 *  can never be zero after a new property is written.
60077 			 */
60078 
60079 			/* E5 Section 15.4.5.1, steps 4.e.i - 4.e.ii */
60080 
60081 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, pending array length update to: %ld",
60082 			                     (long) arridx_new_array_length));
60083 
60084 			a->length = arridx_new_array_length;
60085 		}
60086 
60087 		if (key == DUK_HTHREAD_STRING_LENGTH(thr) && arrlen_new_len < arrlen_old_len) {
60088 			/*
60089 			 *  E5 Section 15.4.5.1, steps 3.k - 3.n.  The order at the end combines
60090 			 *  the error case 3.l.iii and the success case 3.m-3.n.
60091 			 */
60092 
60093 			/* XXX: investigate whether write protect can be handled above, if we
60094 			 * just update length here while ignoring its protected status
60095 			 */
60096 
60097 			duk_uint32_t result_len;
60098 			duk_bool_t rc;
60099 
60100 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key is 'length', exotic array behavior, "
60101 			                     "doing array element deletion and length update"));
60102 
60103 			rc = duk__handle_put_array_length_smaller(thr, obj, arrlen_old_len, arrlen_new_len, force_flag, &result_len);
60104 
60105 			/* update length (curr points to length, and we assume it's still valid) */
60106 			DUK_ASSERT(result_len >= arrlen_new_len && result_len <= arrlen_old_len);
60107 
60108 			a->length = result_len;
60109 
60110 			if (pending_write_protect) {
60111 				DUK_DDD(DUK_DDDPRINT("setting array length non-writable (pending writability update)"));
60112 				DUK_HARRAY_SET_LENGTH_NONWRITABLE(a);
60113 			}
60114 
60115 			/* XXX: shrink array allocation or entries compaction here? */
60116 			if (!rc) {
60117 				DUK_DD(DUK_DDPRINT("array length write only partially successful"));
60118 				goto fail_not_configurable;
60119 			}
60120 		}
60121 	} else if (arr_idx != DUK__NO_ARRAY_INDEX && DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(obj)) {
60122 		duk_hobject *map;
60123 		duk_hobject *varenv;
60124 
60125 		DUK_ASSERT(arridx_new_array_length == 0);
60126 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(obj));  /* traits are separate; in particular, arguments not an array */
60127 
60128 		map = NULL;
60129 		varenv = NULL;
60130 		if (!duk__lookup_arguments_map(thr, obj, key, &curr, &map, &varenv)) {
60131 			goto success_no_exotics;
60132 		}
60133 		DUK_ASSERT(map != NULL);
60134 		DUK_ASSERT(varenv != NULL);
60135 
60136 		/* [obj key desc value get set curr_value varname] */
60137 
60138 		if (has_set || has_get) {
60139 			/* = IsAccessorDescriptor(Desc) */
60140 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map' "
60141 			                     "changed to an accessor, delete arguments binding"));
60142 
60143 			(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60144 		} else {
60145 			/* Note: this order matters (final value before deleting map entry must be done) */
60146 			DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60147 			                     "check for value update / binding deletion"));
60148 
60149 			if (has_value) {
60150 				duk_hstring *varname;
60151 
60152 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60153 				                     "update bound value (variable/argument)"));
60154 
60155 				varname = duk_require_hstring(thr, -1);
60156 				DUK_ASSERT(varname != NULL);
60157 
60158 				DUK_DDD(DUK_DDDPRINT("arguments object automatic putvar for a bound variable; "
60159 				                     "key=%!O, varname=%!O, value=%!T",
60160 				                     (duk_heaphdr *) key,
60161 				                     (duk_heaphdr *) varname,
60162 				                     (duk_tval *) duk_require_tval(thr, idx_value)));
60163 
60164 				/* strict flag for putvar comes from our caller (currently: fixed) */
60165 				duk_js_putvar_envrec(thr, varenv, varname, duk_require_tval(thr, idx_value), 1 /*throw_flag*/);
60166 			}
60167 			if (has_writable && !is_writable) {
60168 				DUK_DDD(DUK_DDDPRINT("defineProperty successful, key mapped to arguments 'map', "
60169 				                     "changed to non-writable, delete arguments binding"));
60170 
60171 				(void) duk_hobject_delprop_raw(thr, map, key, 0);  /* ignore result */
60172 			}
60173 		}
60174 
60175 		/* 'varname' is in stack in this else branch, leaving an unbalanced stack below,
60176 		 * but this doesn't matter now.
60177 		 */
60178 	}
60179 
60180  success_no_exotics:
60181 	/* Some code paths use NORZ macros for simplicity, ensure refzero
60182 	 * handling is completed.
60183 	 */
60184 	DUK_REFZERO_CHECK_SLOW(thr);
60185 	return 1;
60186 
60187  fail_not_extensible:
60188 	if (throw_flag) {
60189 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_EXTENSIBLE);
60190 		DUK_WO_NORETURN(return 0;);
60191 	}
60192 	return 0;
60193 
60194  fail_virtual:  /* just use the same "not configurable" error message" */
60195  fail_not_configurable:
60196 	if (throw_flag) {
60197 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60198 		DUK_WO_NORETURN(return 0;);
60199 	}
60200 	return 0;
60201 }
60202 
60203 /*
60204  *  Object.prototype.hasOwnProperty() and Object.prototype.propertyIsEnumerable().
60205  */
60206 
60207 DUK_INTERNAL duk_bool_t duk_hobject_object_ownprop_helper(duk_hthread *thr, duk_small_uint_t required_desc_flags) {
60208 	duk_hstring *h_v;
60209 	duk_hobject *h_obj;
60210 	duk_propdesc desc;
60211 	duk_bool_t ret;
60212 
60213 	/* coercion order matters */
60214 	h_v = duk_to_hstring_acceptsymbol(thr, 0);
60215 	DUK_ASSERT(h_v != NULL);
60216 
60217 	h_obj = duk_push_this_coercible_to_object(thr);
60218 	DUK_ASSERT(h_obj != NULL);
60219 
60220 	ret = duk_hobject_get_own_propdesc(thr, h_obj, h_v, &desc, 0 /*flags*/);  /* don't push value */
60221 
60222 	duk_push_boolean(thr, ret && ((desc.flags & required_desc_flags) == required_desc_flags));
60223 	return 1;
60224 }
60225 
60226 /*
60227  *  Object.seal() and Object.freeze()  (E5 Sections 15.2.3.8 and 15.2.3.9)
60228  *
60229  *  Since the algorithms are similar, a helper provides both functions.
60230  *  Freezing is essentially sealing + making plain properties non-writable.
60231  *
60232  *  Note: virtual (non-concrete) properties which are non-configurable but
60233  *  writable would pose some problems, but such properties do not currently
60234  *  exist (all virtual properties are non-configurable and non-writable).
60235  *  If they did exist, the non-configurability does NOT prevent them from
60236  *  becoming non-writable.  However, this change should be recorded somehow
60237  *  so that it would turn up (e.g. when getting the property descriptor),
60238  *  requiring some additional flags in the object.
60239  */
60240 
60241 DUK_INTERNAL void duk_hobject_object_seal_freeze_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_freeze) {
60242 	duk_uint_fast32_t i;
60243 
60244 	DUK_ASSERT(thr != NULL);
60245 	DUK_ASSERT(thr->heap != NULL);
60246 	DUK_ASSERT(obj != NULL);
60247 
60248 	DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
60249 
60250 #if defined(DUK_USE_ROM_OBJECTS)
60251 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj)) {
60252 		DUK_DD(DUK_DDPRINT("attempt to seal/freeze a readonly object, reject"));
60253 		DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONFIGURABLE);
60254 		DUK_WO_NORETURN(return;);
60255 	}
60256 #endif
60257 
60258 	/*
60259 	 *  Abandon array part because all properties must become non-configurable.
60260 	 *  Note that this is now done regardless of whether this is always the case
60261 	 *  (skips check, but performance problem if caller would do this many times
60262 	 *  for the same object; not likely).
60263 	 */
60264 
60265 	duk__abandon_array_checked(thr, obj);
60266 	DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(obj) == 0);
60267 
60268 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60269 		duk_uint8_t *fp;
60270 
60271 		/* since duk__abandon_array_checked() causes a resize, there should be no gaps in keys */
60272 		DUK_ASSERT(DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i) != NULL);
60273 
60274 		/* avoid multiple computations of flags address; bypasses macros */
60275 		fp = DUK_HOBJECT_E_GET_FLAGS_PTR(thr->heap, obj, i);
60276 		if (is_freeze && !((*fp) & DUK_PROPDESC_FLAG_ACCESSOR)) {
60277 			*fp &= ~(DUK_PROPDESC_FLAG_WRITABLE | DUK_PROPDESC_FLAG_CONFIGURABLE);
60278 		} else {
60279 			*fp &= ~DUK_PROPDESC_FLAG_CONFIGURABLE;
60280 		}
60281 	}
60282 
60283 	DUK_HOBJECT_CLEAR_EXTENSIBLE(obj);
60284 
60285 	/* no need to compact since we already did that in duk__abandon_array_checked()
60286 	 * (regardless of whether an array part existed or not.
60287 	 */
60288 
60289 	return;
60290 }
60291 
60292 /*
60293  *  Object.isSealed() and Object.isFrozen()  (E5 Sections 15.2.3.11, 15.2.3.13)
60294  *
60295  *  Since the algorithms are similar, a helper provides both functions.
60296  *  Freezing is essentially sealing + making plain properties non-writable.
60297  *
60298  *  Note: all virtual (non-concrete) properties are currently non-configurable
60299  *  and non-writable (and there are no accessor virtual properties), so they don't
60300  *  need to be considered here now.
60301  */
60302 
60303 DUK_INTERNAL duk_bool_t duk_hobject_object_is_sealed_frozen_helper(duk_hthread *thr, duk_hobject *obj, duk_bool_t is_frozen) {
60304 	duk_uint_fast32_t i;
60305 
60306 	DUK_ASSERT(obj != NULL);
60307 	DUK_UNREF(thr);
60308 
60309 	/* Note: no allocation pressure, no need to check refcounts etc */
60310 
60311 	/* must not be extensible */
60312 	if (DUK_HOBJECT_HAS_EXTENSIBLE(obj)) {
60313 		return 0;
60314 	}
60315 
60316 	/* all virtual properties are non-configurable and non-writable */
60317 
60318 	/* entry part must not contain any configurable properties, or
60319 	 * writable properties (if is_frozen).
60320 	 */
60321 	for (i = 0; i < DUK_HOBJECT_GET_ENEXT(obj); i++) {
60322 		duk_small_uint_t flags;
60323 
60324 		if (!DUK_HOBJECT_E_GET_KEY(thr->heap, obj, i)) {
60325 			continue;
60326 		}
60327 
60328 		/* avoid multiple computations of flags address; bypasses macros */
60329 		flags = (duk_small_uint_t) DUK_HOBJECT_E_GET_FLAGS(thr->heap, obj, i);
60330 
60331 		if (flags & DUK_PROPDESC_FLAG_CONFIGURABLE) {
60332 			return 0;
60333 		}
60334 		if (is_frozen &&
60335 		    !(flags & DUK_PROPDESC_FLAG_ACCESSOR) &&
60336 		    (flags & DUK_PROPDESC_FLAG_WRITABLE)) {
60337 			return 0;
60338 		}
60339 	}
60340 
60341 	/* array part must not contain any non-unused properties, as they would
60342 	 * be configurable and writable.
60343 	 */
60344 	for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
60345 		duk_tval *tv = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, obj, i);
60346 		if (!DUK_TVAL_IS_UNUSED(tv)) {
60347 			return 0;
60348 		}
60349 	}
60350 
60351 	return 1;
60352 }
60353 
60354 /*
60355  *  Object.preventExtensions() and Object.isExtensible()  (E5 Sections 15.2.3.10, 15.2.3.13)
60356  *
60357  *  Not needed, implemented by macros DUK_HOBJECT_{HAS,CLEAR,SET}_EXTENSIBLE
60358  *  and the Object built-in bindings.
60359  */
60360 
60361 /* automatic undefs */
60362 #undef DUK__HASH_DELETED
60363 #undef DUK__HASH_UNUSED
60364 #undef DUK__NO_ARRAY_INDEX
60365 #undef DUK__VALSTACK_PROXY_LOOKUP
60366 #undef DUK__VALSTACK_SPACE
60367 #line 1 "duk_hstring_misc.c"
60368 /*
60369  *  Misc support functions
60370  */
60371 
60372 /* #include duk_internal.h -> already included */
60373 
60374 /*
60375  *  duk_hstring charCodeAt, with and without surrogate awareness
60376  */
60377 
60378 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) {
60379 	duk_uint32_t boff;
60380 	const duk_uint8_t *p, *p_start, *p_end;
60381 	duk_ucodepoint_t cp1;
60382 	duk_ucodepoint_t cp2;
60383 
60384 	/* Caller must check character offset to be inside the string. */
60385 	DUK_ASSERT(thr != NULL);
60386 	DUK_ASSERT(h != NULL);
60387 	DUK_ASSERT_DISABLE(pos >= 0);  /* unsigned */
60388 	DUK_ASSERT(pos < (duk_uint_t) DUK_HSTRING_GET_CHARLEN(h));
60389 
60390 	boff = (duk_uint32_t) duk_heap_strcache_offset_char2byte(thr, h, (duk_uint32_t) pos);
60391 	DUK_DDD(DUK_DDDPRINT("charCodeAt: pos=%ld -> boff=%ld, str=%!O",
60392 	                     (long) pos, (long) boff, (duk_heaphdr *) h));
60393 	DUK_ASSERT_DISABLE(boff >= 0);
60394 	DUK_ASSERT(boff < DUK_HSTRING_GET_BYTELEN(h));
60395 
60396 	p_start = DUK_HSTRING_GET_DATA(h);
60397 	p_end = p_start + DUK_HSTRING_GET_BYTELEN(h);
60398 	p = p_start + boff;
60399 	DUK_DDD(DUK_DDDPRINT("p_start=%p, p_end=%p, p=%p",
60400 	                     (const void *) p_start, (const void *) p_end,
60401 	                     (const void *) p));
60402 
60403 	/* For invalid UTF-8 (never happens for standard ECMAScript strings)
60404 	 * return U+FFFD replacement character.
60405 	 */
60406 	if (duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp1)) {
60407 		if (surrogate_aware && cp1 >= 0xd800UL && cp1 <= 0xdbffUL) {
60408 			/* The decode helper is memory safe even if 'cp1' was
60409 			 * decoded at the end of the string and 'p' is no longer
60410 			 * within string memory range.
60411 			 */
60412 			cp2 = 0;  /* If call fails, this is left untouched and won't match cp2 check. */
60413 			(void) duk_unicode_decode_xutf8(thr, &p, p_start, p_end, &cp2);
60414 			if (cp2 >= 0xdc00UL && cp2 <= 0xdfffUL) {
60415 				cp1 = (duk_ucodepoint_t) (((cp1 - 0xd800UL) << 10) + (cp2 - 0xdc00UL) + 0x10000UL);
60416 			}
60417 		}
60418 	} else {
60419 		cp1 = DUK_UNICODE_CP_REPLACEMENT_CHARACTER;
60420 	}
60421 
60422 	return cp1;
60423 }
60424 
60425 /*
60426  *  duk_hstring charlen, when lazy charlen disabled
60427  */
60428 
60429 #if !defined(DUK_USE_HSTRING_LAZY_CLEN)
60430 #if !defined(DUK_USE_HSTRING_CLEN)
60431 #error non-lazy duk_hstring charlen but DUK_USE_HSTRING_CLEN not set
60432 #endif
60433 DUK_INTERNAL void duk_hstring_init_charlen(duk_hstring *h) {
60434 	duk_uint32_t clen;
60435 
60436 	DUK_ASSERT(h != NULL);
60437 	DUK_ASSERT(!DUK_HSTRING_HAS_ASCII(h));
60438 	DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h));
60439 
60440 	clen = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60441 #if defined(DUK_USE_STRLEN16)
60442 	DUK_ASSERT(clen <= 0xffffUL);  /* Bytelength checked during interning. */
60443 	h->clen16 = (duk_uint16_t) clen;
60444 #else
60445 	h->clen = (duk_uint32_t) clen;
60446 #endif
60447 	if (DUK_LIKELY(clen == DUK_HSTRING_GET_BYTELEN(h))) {
60448 		DUK_HSTRING_SET_ASCII(h);
60449 	}
60450 }
60451 
60452 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60453 #if defined(DUK_USE_STRLEN16)
60454 	return h->clen16;
60455 #else
60456 	return h->clen;
60457 #endif
60458 }
60459 #endif  /* !DUK_USE_HSTRING_LAZY_CLEN */
60460 
60461 /*
60462  *  duk_hstring charlen, when lazy charlen enabled
60463  */
60464 
60465 #if defined(DUK_USE_HSTRING_LAZY_CLEN)
60466 #if defined(DUK_USE_HSTRING_CLEN)
60467 DUK_LOCAL DUK_COLD duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
60468 	duk_size_t res;
60469 
60470 	DUK_ASSERT(h->clen == 0);  /* Checked by caller. */
60471 
60472 #if defined(DUK_USE_ROM_STRINGS)
60473 	/* ROM strings have precomputed clen, but if the computed clen is zero
60474 	 * we can still come here and can't write anything.
60475 	 */
60476 	if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
60477 		return 0;
60478 	}
60479 #endif
60480 
60481 	res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60482 #if defined(DUK_USE_STRLEN16)
60483 	DUK_ASSERT(res <= 0xffffUL);  /* Bytelength checked during interning. */
60484 	h->clen16 = (duk_uint16_t) res;
60485 #else
60486 	h->clen = (duk_uint32_t) res;
60487 #endif
60488 	if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
60489 		DUK_HSTRING_SET_ASCII(h);
60490 	}
60491 	return res;
60492 }
60493 #else  /* DUK_USE_HSTRING_CLEN */
60494 DUK_LOCAL duk_size_t duk__hstring_get_charlen_slowpath(duk_hstring *h) {
60495 	if (DUK_LIKELY(DUK_HSTRING_HAS_ASCII(h))) {
60496 		/* Most practical strings will go here. */
60497 		return DUK_HSTRING_GET_BYTELEN(h);
60498 	} else {
60499 		/* ASCII flag is lazy, so set it here. */
60500 		duk_size_t res;
60501 
60502 		/* XXX: here we could use the strcache to speed up the
60503 		 * computation (matters for 'i < str.length' loops).
60504 		 */
60505 
60506 		res = duk_unicode_unvalidated_utf8_length(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h));
60507 
60508 #if defined(DUK_USE_ROM_STRINGS)
60509 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) {
60510 			/* For ROM strings, can't write anything; ASCII flag
60511 			 * is preset so we don't need to update it.
60512 			 */
60513 			return res;
60514 		}
60515 #endif
60516 		if (DUK_LIKELY(res == DUK_HSTRING_GET_BYTELEN(h))) {
60517 			DUK_HSTRING_SET_ASCII(h);
60518 		}
60519 		return res;
60520 	}
60521 }
60522 #endif  /* DUK_USE_HSTRING_CLEN */
60523 
60524 #if defined(DUK_USE_HSTRING_CLEN)
60525 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60526 #if defined(DUK_USE_STRLEN16)
60527 	if (DUK_LIKELY(h->clen16 != 0)) {
60528 		return h->clen16;
60529 	}
60530 #else
60531 	if (DUK_LIKELY(h->clen != 0)) {
60532 		return h->clen;
60533 	}
60534 #endif
60535 	return duk__hstring_get_charlen_slowpath(h);
60536 }
60537 #else  /* DUK_USE_HSTRING_CLEN */
60538 DUK_INTERNAL DUK_HOT duk_size_t duk_hstring_get_charlen(duk_hstring *h) {
60539 	/* Always use slow path. */
60540 	return duk__hstring_get_charlen_slowpath(h);
60541 }
60542 #endif  /* DUK_USE_HSTRING_CLEN */
60543 #endif  /* DUK_USE_HSTRING_LAZY_CLEN */
60544 
60545 /*
60546  *  Compare duk_hstring to an ASCII cstring.
60547  */
60548 
60549 DUK_INTERNAL duk_bool_t duk_hstring_equals_ascii_cstring(duk_hstring *h, const char *cstr) {
60550 	duk_size_t len;
60551 
60552 	DUK_ASSERT(h != NULL);
60553 	DUK_ASSERT(cstr != NULL);
60554 
60555 	len = DUK_STRLEN(cstr);
60556 	if (len != DUK_HSTRING_GET_BYTELEN(h)) {
60557 		return 0;
60558 	}
60559 	if (duk_memcmp((const void *) cstr, (const void *) DUK_HSTRING_GET_DATA(h), len) == 0) {
60560 		return 1;
60561 	}
60562 	return 0;
60563 }
60564 #line 1 "duk_hthread_alloc.c"
60565 /*
60566  *  duk_hthread allocation and freeing.
60567  */
60568 
60569 /* #include duk_internal.h -> already included */
60570 
60571 /*
60572  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
60573  *  as a garbage collection may be triggered by the allocation attempts.
60574  *  Returns zero (without leaking memory) if init fails.
60575  */
60576 
60577 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
60578 	duk_size_t alloc_size;
60579 	duk_size_t i;
60580 
60581 	DUK_ASSERT(heap != NULL);
60582 	DUK_ASSERT(thr != NULL);
60583 	DUK_ASSERT(thr->valstack == NULL);
60584 	DUK_ASSERT(thr->valstack_end == NULL);
60585 	DUK_ASSERT(thr->valstack_alloc_end == NULL);
60586 	DUK_ASSERT(thr->valstack_bottom == NULL);
60587 	DUK_ASSERT(thr->valstack_top == NULL);
60588 	DUK_ASSERT(thr->callstack_curr == NULL);
60589 
60590 	/* valstack */
60591 	DUK_ASSERT(DUK_VALSTACK_API_ENTRY_MINIMUM <= DUK_VALSTACK_INITIAL_SIZE);
60592 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
60593 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
60594 	if (!thr->valstack) {
60595 		goto fail;
60596 	}
60597 	duk_memzero(thr->valstack, alloc_size);
60598 	thr->valstack_end = thr->valstack + DUK_VALSTACK_API_ENTRY_MINIMUM;
60599 	thr->valstack_alloc_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
60600 	thr->valstack_bottom = thr->valstack;
60601 	thr->valstack_top = thr->valstack;
60602 
60603 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
60604 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
60605 	}
60606 
60607 	return 1;
60608 
60609  fail:
60610 	DUK_FREE(heap, thr->valstack);
60611 	DUK_ASSERT(thr->callstack_curr == NULL);
60612 
60613 	thr->valstack = NULL;
60614 	return 0;
60615 }
60616 
60617 /* For indirect allocs. */
60618 
60619 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
60620 	duk_hthread *thr = (duk_hthread *) ud;
60621 	DUK_UNREF(heap);
60622 	return (void *) thr->valstack;
60623 }
60624 #line 1 "duk_hthread_builtins.c"
60625 /*
60626  *  Initialize built-in objects.  Current thread must have a valstack
60627  *  and initialization errors may longjmp, so a setjmp() catch point
60628  *  must exist.
60629  */
60630 
60631 /* #include duk_internal.h -> already included */
60632 
60633 /*
60634  *  Encoding constants, must match genbuiltins.py
60635  */
60636 
60637 #define DUK__PROP_FLAGS_BITS             3
60638 #define DUK__LENGTH_PROP_BITS            3
60639 #define DUK__NARGS_BITS                  3
60640 #define DUK__PROP_TYPE_BITS              3
60641 
60642 #define DUK__NARGS_VARARGS_MARKER        0x07
60643 
60644 #define DUK__PROP_TYPE_DOUBLE            0
60645 #define DUK__PROP_TYPE_STRING            1
60646 #define DUK__PROP_TYPE_STRIDX            2
60647 #define DUK__PROP_TYPE_BUILTIN           3
60648 #define DUK__PROP_TYPE_UNDEFINED         4
60649 #define DUK__PROP_TYPE_BOOLEAN_TRUE      5
60650 #define DUK__PROP_TYPE_BOOLEAN_FALSE     6
60651 #define DUK__PROP_TYPE_ACCESSOR          7
60652 
60653 /*
60654  *  Create built-in objects by parsing an init bitstream generated
60655  *  by genbuiltins.py.
60656  */
60657 
60658 #if defined(DUK_USE_ROM_OBJECTS)
60659 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
60660 DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
60661 	duk_hobject *h_global;
60662 #if defined(DUK_USE_ROM_GLOBAL_CLONE)
60663 	duk_hobject *h_oldglobal;
60664 	duk_uint8_t *props;
60665 	duk_size_t alloc_size;
60666 #endif
60667 	duk_hobject *h_objenv;
60668 
60669 	/* XXX: refactor into internal helper, duk_clone_hobject() */
60670 
60671 #if defined(DUK_USE_ROM_GLOBAL_INHERIT)
60672 	/* Inherit from ROM-based global object: less RAM usage, less transparent. */
60673 	h_global = duk_push_object_helper(thr,
60674 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
60675 	                                  DUK_HOBJECT_FLAG_FASTREFS |
60676 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
60677 	                                  DUK_BIDX_GLOBAL);
60678 	DUK_ASSERT(h_global != NULL);
60679 #elif defined(DUK_USE_ROM_GLOBAL_CLONE)
60680 	/* Clone the properties of the ROM-based global object to create a
60681 	 * fully RAM-based global object.  Uses more memory than the inherit
60682 	 * model but more compliant.
60683 	 */
60684 	h_global = duk_push_object_helper(thr,
60685 	                                  DUK_HOBJECT_FLAG_EXTENSIBLE |
60686 	                                  DUK_HOBJECT_FLAG_FASTREFS |
60687 	                                  DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_GLOBAL),
60688 	                                  DUK_BIDX_OBJECT_PROTOTYPE);
60689 	DUK_ASSERT(h_global != NULL);
60690 	h_oldglobal = thr->builtins[DUK_BIDX_GLOBAL];
60691 	DUK_ASSERT(h_oldglobal != NULL);
60692 
60693 	/* Copy the property table verbatim; this handles attributes etc.
60694 	 * For ROM objects it's not necessary (or possible) to update
60695 	 * refcounts so leave them as is.
60696 	 */
60697 	alloc_size = DUK_HOBJECT_P_ALLOC_SIZE(h_oldglobal);
60698 	DUK_ASSERT(alloc_size > 0);
60699 	props = DUK_ALLOC_CHECKED(thr, alloc_size);
60700 	DUK_ASSERT(props != NULL);
60701 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal) != NULL);
60702 	duk_memcpy((void *) props, (const void *) DUK_HOBJECT_GET_PROPS(thr->heap, h_oldglobal), alloc_size);
60703 
60704 	/* XXX: keep property attributes or tweak them here?
60705 	 * Properties will now be non-configurable even when they're
60706 	 * normally configurable for the global object.
60707 	 */
60708 
60709 	DUK_ASSERT(DUK_HOBJECT_GET_PROPS(thr->heap, h_global) == NULL);
60710 	DUK_HOBJECT_SET_PROPS(thr->heap, h_global, props);
60711 	DUK_HOBJECT_SET_ESIZE(h_global, DUK_HOBJECT_GET_ESIZE(h_oldglobal));
60712 	DUK_HOBJECT_SET_ENEXT(h_global, DUK_HOBJECT_GET_ENEXT(h_oldglobal));
60713 	DUK_HOBJECT_SET_ASIZE(h_global, DUK_HOBJECT_GET_ASIZE(h_oldglobal));
60714 	DUK_HOBJECT_SET_HSIZE(h_global, DUK_HOBJECT_GET_HSIZE(h_oldglobal));
60715 #else
60716 #error internal error in config defines
60717 #endif
60718 
60719 	duk_hobject_compact_props(thr, h_global);
60720 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL] != NULL);
60721 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL]));  /* no need to decref: ROM object */
60722 	thr->builtins[DUK_BIDX_GLOBAL] = h_global;
60723 	DUK_HOBJECT_INCREF(thr, h_global);
60724 	DUK_D(DUK_DPRINT("duplicated global object: %!O", h_global));
60725 
60726 	/* Create a fresh object environment for the global scope.  This is
60727 	 * needed so that the global scope points to the newly created RAM-based
60728 	 * global object.
60729 	 */
60730 	h_objenv = (duk_hobject *) duk_hobjenv_alloc(thr,
60731 	                                             DUK_HOBJECT_FLAG_EXTENSIBLE |
60732 	                                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
60733 	DUK_ASSERT(h_objenv != NULL);
60734 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_objenv) == NULL);
60735 	duk_push_hobject(thr, h_objenv);
60736 
60737 	DUK_ASSERT(h_global != NULL);
60738 	((duk_hobjenv *) h_objenv)->target = h_global;
60739 	DUK_HOBJECT_INCREF(thr, h_global);
60740 	DUK_ASSERT(((duk_hobjenv *) h_objenv)->has_this == 0);
60741 
60742 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
60743 	DUK_ASSERT(!DUK_HEAPHDR_NEEDS_REFCOUNT_UPDATE((duk_heaphdr *) thr->builtins[DUK_BIDX_GLOBAL_ENV]));  /* no need to decref: ROM object */
60744 	thr->builtins[DUK_BIDX_GLOBAL_ENV] = h_objenv;
60745 	DUK_HOBJECT_INCREF(thr, h_objenv);
60746 	DUK_D(DUK_DPRINT("duplicated global env: %!O", h_objenv));
60747 
60748 	DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) h_objenv);
60749 
60750 	duk_pop_2(thr);  /* Pop global object and global env. */
60751 }
60752 #endif  /* DUK_USE_ROM_GLOBAL_CLONE || DUK_USE_ROM_GLOBAL_INHERIT */
60753 
60754 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
60755 	/* Setup builtins from ROM objects.  All heaps/threads will share
60756 	 * the same readonly objects.
60757 	 */
60758 	duk_small_uint_t i;
60759 
60760 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
60761 		duk_hobject *h;
60762 		h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]);
60763 		DUK_ASSERT(h != NULL);
60764 		thr->builtins[i] = h;
60765 	}
60766 
60767 #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT)
60768 	/* By default the global object is read-only which is often much
60769 	 * more of an issue than having read-only built-in objects (like
60770 	 * RegExp, Date, etc).  Use a RAM-based copy of the global object
60771 	 * and the global environment object for convenience.
60772 	 */
60773 	duk__duplicate_ram_global_object(thr);
60774 #endif
60775 }
60776 #else  /* DUK_USE_ROM_OBJECTS */
60777 DUK_LOCAL void duk__push_stridx(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60778 	duk_small_uint_t n;
60779 
60780 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60781 	DUK_ASSERT_DISABLE(n >= 0);  /* unsigned */
60782 	DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
60783 	duk_push_hstring_stridx(thr, n);
60784 }
60785 DUK_LOCAL void duk__push_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60786 	/* XXX: built-ins data could provide a maximum length that is
60787 	 * actually needed; bitpacked max length is now 256 bytes.
60788 	 */
60789 	duk_uint8_t tmp[DUK_BD_BITPACKED_STRING_MAXLEN];
60790 	duk_small_uint_t len;
60791 
60792 	len = duk_bd_decode_bitpacked_string(bd, tmp);
60793 	duk_push_lstring(thr, (const char *) tmp, (duk_size_t) len);
60794 }
60795 DUK_LOCAL void duk__push_stridx_or_string(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60796 	duk_small_uint_t n;
60797 
60798 	n = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60799 	if (n == 0) {
60800 		duk__push_string(thr, bd);
60801 	} else {
60802 		n--;
60803 		DUK_ASSERT(n < DUK_HEAP_NUM_STRINGS);
60804 		duk_push_hstring_stridx(thr, n);
60805 	}
60806 }
60807 DUK_LOCAL void duk__push_double(duk_hthread *thr, duk_bitdecoder_ctx *bd) {
60808 	duk_double_union du;
60809 	duk_small_uint_t i;
60810 
60811 	for (i = 0; i < 8; i++) {
60812 		/* Encoding endianness must match target memory layout,
60813 		 * build scripts and genbuiltins.py must ensure this.
60814 		 */
60815 		du.uc[i] = (duk_uint8_t) duk_bd_decode(bd, 8);
60816 	}
60817 
60818 	duk_push_number(thr, du.d);  /* push operation normalizes NaNs */
60819 }
60820 
60821 DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) {
60822 	duk_bitdecoder_ctx bd_ctx;
60823 	duk_bitdecoder_ctx *bd = &bd_ctx;  /* convenience */
60824 	duk_hobject *h;
60825 	duk_small_uint_t i, j;
60826 
60827 	DUK_D(DUK_DPRINT("INITBUILTINS BEGIN: DUK_NUM_BUILTINS=%d, DUK_NUM_BUILTINS_ALL=%d", (int) DUK_NUM_BUILTINS, (int) DUK_NUM_ALL_BUILTINS));
60828 
60829 	duk_memzero(&bd_ctx, sizeof(bd_ctx));
60830 	bd->data = (const duk_uint8_t *) duk_builtins_data;
60831 	bd->length = (duk_size_t) DUK_BUILTINS_DATA_LENGTH;
60832 
60833 	/*
60834 	 *  First create all built-in bare objects on the empty valstack.
60835 	 *
60836 	 *  Built-ins in the index range [0,DUK_NUM_BUILTINS-1] have value
60837 	 *  stack indices matching their eventual thr->builtins[] index.
60838 	 *
60839 	 *  Built-ins in the index range [DUK_NUM_BUILTINS,DUK_NUM_ALL_BUILTINS]
60840 	 *  will exist on the value stack during init but won't be placed
60841 	 *  into thr->builtins[].  These are objects referenced in some way
60842 	 *  from thr->builtins[] roots but which don't need to be indexed by
60843 	 *  Duktape through thr->builtins[] (e.g. user custom objects).
60844 	 *
60845 	 *  Internal prototypes will be incorrect (NULL) at this stage.
60846 	 */
60847 
60848 	duk_require_stack(thr, DUK_NUM_ALL_BUILTINS);
60849 
60850 	DUK_DD(DUK_DDPRINT("create empty built-ins"));
60851 	DUK_ASSERT_TOP(thr, 0);
60852 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
60853 		duk_small_uint_t class_num;
60854 		duk_small_int_t len = -1;  /* must be signed */
60855 
60856 		class_num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60857 		len = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__LENGTH_PROP_BITS, (duk_int32_t) -1 /*def_value*/);
60858 
60859 		if (class_num == DUK_HOBJECT_CLASS_FUNCTION) {
60860 			duk_small_uint_t natidx;
60861 			duk_small_int_t c_nargs;  /* must hold DUK_VARARGS */
60862 			duk_c_function c_func;
60863 			duk_int16_t magic;
60864 
60865 			DUK_DDD(DUK_DDDPRINT("len=%ld", (long) len));
60866 			DUK_ASSERT(len >= 0);
60867 
60868 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
60869 			DUK_ASSERT(natidx != 0);
60870 			c_func = duk_bi_native_functions[natidx];
60871 			DUK_ASSERT(c_func != NULL);
60872 
60873 			c_nargs = (duk_small_int_t) duk_bd_decode_flagged_signed(bd, DUK__NARGS_BITS, len /*def_value*/);
60874 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
60875 				c_nargs = DUK_VARARGS;
60876 			}
60877 
60878 			/* XXX: set magic directly here? (it could share the c_nargs arg) */
60879 			(void) duk_push_c_function_builtin(thr, c_func, c_nargs);
60880 			h = duk_known_hobject(thr, -1);
60881 
60882 			/* Currently all built-in native functions are strict.
60883 			 * duk_push_c_function() now sets strict flag, so
60884 			 * assert for it.
60885 			 */
60886 			DUK_ASSERT(DUK_HOBJECT_HAS_STRICT(h));
60887 
60888 			/* XXX: function properties */
60889 
60890 			duk__push_stridx_or_string(thr, bd);
60891 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
60892 			duk_xdef_prop_stridx_short(thr,
60893 			                           -2,
60894 			                           DUK_STRIDX_NAME,
60895 			                           DUK_PROPDESC_FLAGS_C);
60896 #else
60897 			duk_pop(thr);  /* Not very ideal but good enough for now. */
60898 #endif
60899 
60900 			/* Almost all global level Function objects are constructable
60901 			 * but not all: Function.prototype is a non-constructable,
60902 			 * callable Function.
60903 			 */
60904 			if (duk_bd_decode_flag(bd)) {
60905 				DUK_ASSERT(DUK_HOBJECT_HAS_CONSTRUCTABLE(h));
60906 			} else {
60907 				DUK_HOBJECT_CLEAR_CONSTRUCTABLE(h);
60908 			}
60909 
60910 			/* Cast converts magic to 16-bit signed value */
60911 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
60912 			((duk_hnatfunc *) h)->magic = magic;
60913 		} else if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
60914 			duk_push_array(thr);
60915 		} else if (class_num == DUK_HOBJECT_CLASS_OBJENV) {
60916 			duk_hobjenv *env;
60917 			duk_hobject *global;
60918 
60919 			DUK_ASSERT(i == DUK_BIDX_GLOBAL_ENV);
60920 			DUK_ASSERT(DUK_BIDX_GLOBAL_ENV > DUK_BIDX_GLOBAL);
60921 
60922 			env = duk_hobjenv_alloc(thr,
60923 	                                        DUK_HOBJECT_FLAG_EXTENSIBLE |
60924 	                                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
60925 			DUK_ASSERT(env->target == NULL);
60926 			duk_push_hobject(thr, (duk_hobject *) env);
60927 
60928 			global = duk_known_hobject(thr, DUK_BIDX_GLOBAL);
60929 			DUK_ASSERT(global != NULL);
60930 			env->target = global;
60931 			DUK_HOBJECT_INCREF(thr, global);
60932 			DUK_ASSERT(env->has_this == 0);
60933 
60934 			DUK_ASSERT_HOBJENV_VALID(env);
60935 		} else {
60936 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_DECENV);
60937 
60938 			(void) duk_push_object_helper(thr,
60939 			                              DUK_HOBJECT_FLAG_FASTREFS |
60940 			                              DUK_HOBJECT_FLAG_EXTENSIBLE,
60941 			                              -1);  /* no prototype or class yet */
60942 
60943 		}
60944 
60945 		h = duk_known_hobject(thr, -1);
60946 		DUK_HOBJECT_SET_CLASS_NUMBER(h, class_num);
60947 
60948 		if (i < DUK_NUM_BUILTINS) {
60949 			thr->builtins[i] = h;
60950 			DUK_HOBJECT_INCREF(thr, &h->hdr);
60951 		}
60952 
60953 		if (len >= 0) {
60954 			/* In ES2015+ built-in function object .length property
60955 			 * has property attributes C (configurable only):
60956 			 * http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-standard-built-in-objects
60957 			 *
60958 			 * Array.prototype remains an Array instance in ES2015+
60959 			 * and its length has attributes W (writable only).
60960 			 * Because .length is now virtual for duk_harray, it is
60961 			 * not encoded explicitly in init data.
60962 			 */
60963 
60964 			DUK_ASSERT(class_num != DUK_HOBJECT_CLASS_ARRAY);  /* .length is virtual */
60965 			duk_push_int(thr, len);
60966 			duk_xdef_prop_stridx_short(thr,
60967 			                           -2,
60968 			                           DUK_STRIDX_LENGTH,
60969 			                           DUK_PROPDESC_FLAGS_C);
60970 		}
60971 
60972 		/* enable exotic behaviors last */
60973 
60974 		if (class_num == DUK_HOBJECT_CLASS_ARRAY) {
60975 			DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h));  /* set by duk_push_array() */
60976 		}
60977 		if (class_num == DUK_HOBJECT_CLASS_STRING) {
60978 			DUK_HOBJECT_SET_EXOTIC_STRINGOBJ(h);
60979 		}
60980 
60981 		/* some assertions */
60982 
60983 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h));
60984 		/* DUK_HOBJECT_FLAG_CONSTRUCTABLE varies */
60985 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(h));
60986 		DUK_ASSERT(!DUK_HOBJECT_HAS_COMPFUNC(h));
60987 		/* DUK_HOBJECT_FLAG_NATFUNC varies */
60988 		DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(h));
60989 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(h) || class_num == DUK_HOBJECT_CLASS_ARRAY);
60990 		/* DUK_HOBJECT_FLAG_STRICT varies */
60991 		DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(h) ||  /* all native functions have NEWENV */
60992 		           DUK_HOBJECT_HAS_NEWENV(h));
60993 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(h));
60994 		DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(h));
60995 		/* DUK_HOBJECT_FLAG_EXOTIC_ARRAY varies */
60996 		/* DUK_HOBJECT_FLAG_EXOTIC_STRINGOBJ varies */
60997 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(h));
60998 
60999 		DUK_DDD(DUK_DDDPRINT("created built-in %ld, class=%ld, length=%ld", (long) i, (long) class_num, (long) len));
61000 	}
61001 
61002 	/*
61003 	 *  Then decode the builtins init data (see genbuiltins.py) to
61004 	 *  init objects.  Internal prototypes are set at this stage,
61005 	 *  with thr->builtins[] populated.
61006 	 */
61007 
61008 	DUK_DD(DUK_DDPRINT("initialize built-in object properties"));
61009 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61010 		duk_small_uint_t t;
61011 		duk_small_uint_t num;
61012 
61013 		DUK_DDD(DUK_DDDPRINT("initializing built-in object at index %ld", (long) i));
61014 		h = duk_known_hobject(thr, (duk_idx_t) i);
61015 
61016 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61017 		if (t > 0) {
61018 			t--;
61019 			DUK_DDD(DUK_DDDPRINT("set internal prototype: built-in %ld", (long) t));
61020 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, duk_known_hobject(thr, (duk_idx_t) t));
61021 		} else if (DUK_HOBJECT_IS_NATFUNC(h)) {
61022 			/* Standard native built-ins cannot inherit from
61023 			 * %NativeFunctionPrototype%, they are required to
61024 			 * inherit from Function.prototype directly.
61025 			 */
61026 			DUK_ASSERT(thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE] != NULL);
61027 			DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
61028 		}
61029 
61030 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61031 		if (t > 0) {
61032 			/* 'prototype' property for all built-in objects (which have it) has attributes:
61033 			 *  [[Writable]] = false,
61034 			 *  [[Enumerable]] = false,
61035 			 *  [[Configurable]] = false
61036 			 */
61037 			t--;
61038 			DUK_DDD(DUK_DDDPRINT("set external prototype: built-in %ld", (long) t));
61039 			duk_dup(thr, (duk_idx_t) t);
61040 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_NONE);
61041 		}
61042 
61043 		t = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61044 		if (t > 0) {
61045 			/* 'constructor' property for all built-in objects (which have it) has attributes:
61046 			 *  [[Writable]] = true,
61047 			 *  [[Enumerable]] = false,
61048 			 *  [[Configurable]] = true
61049 			 */
61050 			t--;
61051 			DUK_DDD(DUK_DDDPRINT("set external constructor: built-in %ld", (long) t));
61052 			duk_dup(thr, (duk_idx_t) t);
61053 			duk_xdef_prop_stridx(thr, (duk_idx_t) i, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);
61054 		}
61055 
61056 		/* normal valued properties */
61057 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61058 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld normal valued properties", (long) i, (long) num));
61059 		for (j = 0; j < num; j++) {
61060 			duk_small_uint_t defprop_flags;
61061 
61062 			duk__push_stridx_or_string(thr, bd);
61063 
61064 			/*
61065 			 *  Property attribute defaults are defined in E5 Section 15 (first
61066 			 *  few pages); there is a default for all properties and a special
61067 			 *  default for 'length' properties.  Variation from the defaults is
61068 			 *  signaled using a single flag bit in the bitstream.
61069 			 */
61070 
61071 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61072 			                                                         DUK__PROP_FLAGS_BITS,
61073 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61074 			defprop_flags |= DUK_DEFPROP_FORCE |
61075 			                 DUK_DEFPROP_HAVE_VALUE |
61076 			                 DUK_DEFPROP_HAVE_WRITABLE |
61077 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61078 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;  /* Defaults for data properties. */
61079 
61080 			/* The writable, enumerable, configurable flags in prop_flags
61081 			 * match both duk_def_prop() and internal property flags.
61082 			 */
61083 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61084 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61085 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61086 
61087 			t = (duk_small_uint_t) duk_bd_decode(bd, DUK__PROP_TYPE_BITS);
61088 
61089 			DUK_DDD(DUK_DDDPRINT("built-in %ld, normal-valued property %ld, key %!T, flags 0x%02lx, type %ld",
61090 			                     (long) i, (long) j, duk_get_tval(thr, -1), (unsigned long) defprop_flags, (long) t));
61091 
61092 			switch (t) {
61093 			case DUK__PROP_TYPE_DOUBLE: {
61094 				duk__push_double(thr, bd);
61095 				break;
61096 			}
61097 			case DUK__PROP_TYPE_STRING: {
61098 				duk__push_string(thr, bd);
61099 				break;
61100 			}
61101 			case DUK__PROP_TYPE_STRIDX: {
61102 				duk__push_stridx(thr, bd);
61103 				break;
61104 			}
61105 			case DUK__PROP_TYPE_BUILTIN: {
61106 				duk_small_uint_t bidx;
61107 
61108 				bidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61109 				duk_dup(thr, (duk_idx_t) bidx);
61110 				break;
61111 			}
61112 			case DUK__PROP_TYPE_UNDEFINED: {
61113 				duk_push_undefined(thr);
61114 				break;
61115 			}
61116 			case DUK__PROP_TYPE_BOOLEAN_TRUE: {
61117 				duk_push_true(thr);
61118 				break;
61119 			}
61120 			case DUK__PROP_TYPE_BOOLEAN_FALSE: {
61121 				duk_push_false(thr);
61122 				break;
61123 			}
61124 			case DUK__PROP_TYPE_ACCESSOR: {
61125 				duk_small_uint_t natidx_getter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61126 				duk_small_uint_t natidx_setter = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61127 				duk_small_uint_t accessor_magic = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61128 				duk_c_function c_func_getter;
61129 				duk_c_function c_func_setter;
61130 
61131 				DUK_DDD(DUK_DDDPRINT("built-in accessor property: objidx=%ld, key=%!T, getteridx=%ld, setteridx=%ld, flags=0x%04lx",
61132 				                     (long) i, duk_get_tval(thr, -1), (long) natidx_getter, (long) natidx_setter, (unsigned long) defprop_flags));
61133 
61134 				c_func_getter = duk_bi_native_functions[natidx_getter];
61135 				if (c_func_getter != NULL) {
61136 					duk_push_c_function_builtin_noconstruct(thr, c_func_getter, 0);  /* always 0 args */
61137 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61138 					defprop_flags |= DUK_DEFPROP_HAVE_GETTER;
61139 				}
61140 				c_func_setter = duk_bi_native_functions[natidx_setter];
61141 				if (c_func_setter != NULL) {
61142 					duk_push_c_function_builtin_noconstruct(thr, c_func_setter, 1);  /* always 1 arg */
61143 					duk_set_magic(thr, -1, (duk_int_t) accessor_magic);
61144 					defprop_flags |= DUK_DEFPROP_HAVE_SETTER;
61145 				}
61146 
61147 				/* Writable flag doesn't make sense for an accessor. */
61148 				DUK_ASSERT((defprop_flags & DUK_PROPDESC_FLAG_WRITABLE) == 0);  /* genbuiltins.py ensures */
61149 
61150 				defprop_flags &= ~(DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_HAVE_WRITABLE);
61151 				defprop_flags |= DUK_DEFPROP_HAVE_ENUMERABLE | DUK_DEFPROP_HAVE_CONFIGURABLE;
61152 				break;
61153 			}
61154 			default: {
61155 				/* exhaustive */
61156 				DUK_UNREACHABLE();
61157 			}
61158 			}
61159 
61160 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61161 			DUK_ASSERT_TOP(thr, DUK_NUM_ALL_BUILTINS);
61162 		}
61163 
61164 		/* native function properties */
61165 		num = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61166 		DUK_DDD(DUK_DDDPRINT("built-in object %ld, %ld function valued properties", (long) i, (long) num));
61167 		for (j = 0; j < num; j++) {
61168 			duk_hstring *h_key;
61169 			duk_small_uint_t natidx;
61170 			duk_int_t c_nargs;  /* must hold DUK_VARARGS */
61171 			duk_small_uint_t c_length;
61172 			duk_int16_t magic;
61173 			duk_c_function c_func;
61174 			duk_hnatfunc *h_func;
61175 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61176 			duk_small_int_t lightfunc_eligible;
61177 #endif
61178 			duk_small_uint_t defprop_flags;
61179 
61180 			duk__push_stridx_or_string(thr, bd);
61181 			h_key = duk_known_hstring(thr, -1);
61182 			DUK_UNREF(h_key);
61183 			natidx = (duk_small_uint_t) duk_bd_decode_varuint(bd);
61184 
61185 			c_length = (duk_small_uint_t) duk_bd_decode(bd, DUK__LENGTH_PROP_BITS);
61186 			c_nargs = (duk_int_t) duk_bd_decode_flagged(bd, DUK__NARGS_BITS, (duk_uint32_t) c_length /*def_value*/);
61187 			if (c_nargs == DUK__NARGS_VARARGS_MARKER) {
61188 				c_nargs = DUK_VARARGS;
61189 			}
61190 
61191 			c_func = duk_bi_native_functions[natidx];
61192 
61193 			DUK_DDD(DUK_DDDPRINT("built-in %ld, function-valued property %ld, key %!O, natidx %ld, length %ld, nargs %ld",
61194 			                     (long) i, (long) j, (duk_heaphdr *) h_key, (long) natidx, (long) c_length,
61195 			                     (c_nargs == DUK_VARARGS ? (long) -1 : (long) c_nargs)));
61196 
61197 			/* Cast converts magic to 16-bit signed value */
61198 			magic = (duk_int16_t) duk_bd_decode_varuint(bd);
61199 
61200 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61201 			lightfunc_eligible =
61202 				((c_nargs >= DUK_LFUNC_NARGS_MIN && c_nargs <= DUK_LFUNC_NARGS_MAX) || (c_nargs == DUK_VARARGS)) &&
61203 				(c_length <= DUK_LFUNC_LENGTH_MAX) &&
61204 				(magic >= DUK_LFUNC_MAGIC_MIN && magic <= DUK_LFUNC_MAGIC_MAX);
61205 
61206 			/* These functions have trouble working as lightfuncs.
61207 			 * Some of them have specific asserts and some may have
61208 		         * additional properties (e.g. 'require.id' may be written).
61209 			 */
61210 			if (c_func == duk_bi_global_object_eval) {
61211 				lightfunc_eligible = 0;
61212 			}
61213 #if defined(DUK_USE_COROUTINE_SUPPORT)
61214 			if (c_func == duk_bi_thread_yield ||
61215 			    c_func == duk_bi_thread_resume) {
61216 				lightfunc_eligible = 0;
61217 			}
61218 #endif
61219 			if (c_func == duk_bi_function_prototype_call ||
61220 			    c_func == duk_bi_function_prototype_apply ||
61221 			    c_func == duk_bi_reflect_apply ||
61222 			    c_func == duk_bi_reflect_construct) {
61223 				lightfunc_eligible = 0;
61224 			}
61225 
61226 			if (lightfunc_eligible) {
61227 				duk_tval tv_lfunc;
61228 				duk_small_uint_t lf_nargs = (duk_small_uint_t) (c_nargs == DUK_VARARGS ? DUK_LFUNC_NARGS_VARARGS : c_nargs);
61229 				duk_small_uint_t lf_flags = DUK_LFUNC_FLAGS_PACK(magic, c_length, lf_nargs);
61230 				DUK_TVAL_SET_LIGHTFUNC(&tv_lfunc, c_func, lf_flags);
61231 				duk_push_tval(thr, &tv_lfunc);
61232 				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)));
61233 				goto lightfunc_skip;
61234 			}
61235 
61236 			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));
61237 #endif  /* DUK_USE_LIGHTFUNC_BUILTINS */
61238 
61239 			/* [ (builtin objects) name ] */
61240 
61241 			duk_push_c_function_builtin_noconstruct(thr, c_func, c_nargs);
61242 			h_func = duk_known_hnatfunc(thr, -1);
61243 			DUK_UNREF(h_func);
61244 
61245 			/* XXX: add into init data? */
61246 
61247 			/* Special call handling, not described in init data. */
61248 			if (c_func == duk_bi_global_object_eval ||
61249 			    c_func == duk_bi_function_prototype_call ||
61250 			    c_func == duk_bi_function_prototype_apply ||
61251 			    c_func == duk_bi_reflect_apply ||
61252 			    c_func == duk_bi_reflect_construct) {
61253 				DUK_HOBJECT_SET_SPECIAL_CALL((duk_hobject *) h_func);
61254 			}
61255 
61256 			/* Currently all built-in native functions are strict.
61257 			 * This doesn't matter for many functions, but e.g.
61258 			 * String.prototype.charAt (and other string functions)
61259 			 * rely on being strict so that their 'this' binding is
61260 			 * not automatically coerced.
61261 			 */
61262 			DUK_HOBJECT_SET_STRICT((duk_hobject *) h_func);
61263 
61264 			/* No built-in functions are constructable except the top
61265 			 * level ones (Number, etc).
61266 			 */
61267 			DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE((duk_hobject *) h_func));
61268 
61269 			/* XXX: any way to avoid decoding magic bit; there are quite
61270 			 * many function properties and relatively few with magic values.
61271 			 */
61272 			h_func->magic = magic;
61273 
61274 			/* [ (builtin objects) name func ] */
61275 
61276 			duk_push_uint(thr, c_length);
61277 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
61278 
61279 			duk_dup_m2(thr);
61280 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);
61281 
61282 			/* XXX: other properties of function instances; 'arguments', 'caller'. */
61283 
61284 			DUK_DD(DUK_DDPRINT("built-in object %ld, function property %ld -> %!T",
61285 			                   (long) i, (long) j, (duk_tval *) duk_get_tval(thr, -1)));
61286 
61287 			/* [ (builtin objects) name func ] */
61288 
61289 			/*
61290 			 *  The default property attributes are correct for all
61291 			 *  function valued properties of built-in objects now.
61292 			 */
61293 
61294 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61295 		 lightfunc_skip:
61296 #endif
61297 
61298 			defprop_flags = (duk_small_uint_t) duk_bd_decode_flagged(bd,
61299 			                                                         DUK__PROP_FLAGS_BITS,
61300 			                                                         (duk_uint32_t) DUK_PROPDESC_FLAGS_WC);
61301 			defprop_flags |= DUK_DEFPROP_FORCE |
61302 			                 DUK_DEFPROP_HAVE_VALUE |
61303 			                 DUK_DEFPROP_HAVE_WRITABLE |
61304 			                 DUK_DEFPROP_HAVE_ENUMERABLE |
61305 			                 DUK_DEFPROP_HAVE_CONFIGURABLE;
61306 			DUK_ASSERT(DUK_PROPDESC_FLAG_WRITABLE == DUK_DEFPROP_WRITABLE);
61307 			DUK_ASSERT(DUK_PROPDESC_FLAG_ENUMERABLE == DUK_DEFPROP_ENUMERABLE);
61308 			DUK_ASSERT(DUK_PROPDESC_FLAG_CONFIGURABLE == DUK_DEFPROP_CONFIGURABLE);
61309 
61310 			duk_def_prop(thr, (duk_idx_t) i, defprop_flags);
61311 
61312 			/* [ (builtin objects) ] */
61313 		}
61314 	}
61315 
61316 	/*
61317 	 *  Special post-tweaks, for cases not covered by the init data format.
61318 	 *
61319 	 *  - Set Date.prototype.toGMTString to Date.prototype.toUTCString.
61320 	 *    toGMTString is required to have the same Function object as
61321 	 *    toUTCString in E5 Section B.2.6.  Note that while Smjs respects
61322 	 *    this, V8 does not (the Function objects are distinct).
61323 	 *
61324 	 *  - Make DoubleError non-extensible.
61325 	 *
61326 	 *  - Add info about most important effective compile options to Duktape.
61327 	 *
61328 	 *  - Possibly remove some properties (values or methods) which are not
61329 	 *    desirable with current feature options but are not currently
61330 	 *    conditional in init data.
61331 	 */
61332 
61333 #if defined(DUK_USE_DATE_BUILTIN)
61334 	duk_get_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_UTC_STRING);
61335 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DATE_PROTOTYPE, DUK_STRIDX_TO_GMT_STRING, DUK_PROPDESC_FLAGS_WC);
61336 #endif
61337 
61338 	h = duk_known_hobject(thr, DUK_BIDX_DOUBLE_ERROR);
61339 	DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
61340 
61341 #if !defined(DUK_USE_ES6_OBJECT_PROTO_PROPERTY)
61342 	DUK_DD(DUK_DDPRINT("delete Object.prototype.__proto__ built-in which is not enabled in features"));
61343 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_PROTOTYPE], DUK_HTHREAD_STRING___PROTO__(thr), DUK_DELPROP_FLAG_THROW);
61344 #endif
61345 
61346 #if !defined(DUK_USE_ES6_OBJECT_SETPROTOTYPEOF)
61347 	DUK_DD(DUK_DDPRINT("delete Object.setPrototypeOf built-in which is not enabled in features"));
61348 	(void) duk_hobject_delprop_raw(thr, thr->builtins[DUK_BIDX_OBJECT_CONSTRUCTOR], DUK_HTHREAD_STRING_SET_PROTOTYPE_OF(thr), DUK_DELPROP_FLAG_THROW);
61349 #endif
61350 
61351 	/* XXX: relocate */
61352 	duk_push_string(thr,
61353 			/* Endianness indicator */
61354 #if defined(DUK_USE_INTEGER_LE)
61355 	                "l"
61356 #elif defined(DUK_USE_INTEGER_BE)
61357 	                "b"
61358 #elif defined(DUK_USE_INTEGER_ME)  /* integer mixed endian not really used now */
61359 	                "m"
61360 #else
61361 	                "?"
61362 #endif
61363 #if defined(DUK_USE_DOUBLE_LE)
61364 	                "l"
61365 #elif defined(DUK_USE_DOUBLE_BE)
61366 	                "b"
61367 #elif defined(DUK_USE_DOUBLE_ME)
61368 	                "m"
61369 #else
61370 	                "?"
61371 #endif
61372 	                " "
61373 			/* Packed or unpacked tval */
61374 #if defined(DUK_USE_PACKED_TVAL)
61375 	                "p"
61376 #else
61377 	                "u"
61378 #endif
61379 #if defined(DUK_USE_FASTINT)
61380 			"f"
61381 #endif
61382 			" "
61383 			/* Low memory/performance options */
61384 #if defined(DUK_USE_STRTAB_PTRCOMP)
61385 			"s"
61386 #endif
61387 #if !defined(DUK_USE_HEAPPTR16) && !defined(DUK_DATAPTR16) && !defined(DUK_FUNCPTR16)
61388 			"n"
61389 #endif
61390 #if defined(DUK_USE_HEAPPTR16)
61391 			"h"
61392 #endif
61393 #if defined(DUK_USE_DATAPTR16)
61394 			"d"
61395 #endif
61396 #if defined(DUK_USE_FUNCPTR16)
61397 			"f"
61398 #endif
61399 #if defined(DUK_USE_REFCOUNT16)
61400 			"R"
61401 #endif
61402 #if defined(DUK_USE_STRHASH16)
61403 			"H"
61404 #endif
61405 #if defined(DUK_USE_STRLEN16)
61406 			"S"
61407 #endif
61408 #if defined(DUK_USE_BUFLEN16)
61409 			"B"
61410 #endif
61411 #if defined(DUK_USE_OBJSIZES16)
61412 			"O"
61413 #endif
61414 #if defined(DUK_USE_LIGHTFUNC_BUILTINS)
61415 			"L"
61416 #endif
61417 #if defined(DUK_USE_ROM_STRINGS) || defined(DUK_USE_ROM_OBJECTS)
61418 			/* XXX: This won't be shown in practice now
61419 			 * because this code is not run when builtins
61420 			 * are in ROM.
61421 			 */
61422 			"Z"
61423 #endif
61424 #if defined(DUK_USE_LITCACHE_SIZE)
61425 			"l"
61426 #endif
61427 	                " "
61428 			/* Object property allocation layout */
61429 #if defined(DUK_USE_HOBJECT_LAYOUT_1)
61430 			"p1"
61431 #elif defined(DUK_USE_HOBJECT_LAYOUT_2)
61432 			"p2"
61433 #elif defined(DUK_USE_HOBJECT_LAYOUT_3)
61434 			"p3"
61435 #else
61436 			"p?"
61437 #endif
61438 			" "
61439 			/* Alignment guarantee */
61440 #if (DUK_USE_ALIGN_BY == 4)
61441 			"a4"
61442 #elif (DUK_USE_ALIGN_BY == 8)
61443 			"a8"
61444 #elif (DUK_USE_ALIGN_BY == 1)
61445 			"a1"
61446 #else
61447 #error invalid DUK_USE_ALIGN_BY
61448 #endif
61449 			" "
61450 			/* Architecture, OS, and compiler strings */
61451 	                DUK_USE_ARCH_STRING
61452 			" "
61453 	                DUK_USE_OS_STRING
61454 			" "
61455 	                DUK_USE_COMPILER_STRING);
61456 	duk_xdef_prop_stridx_short(thr, DUK_BIDX_DUKTAPE, DUK_STRIDX_ENV, DUK_PROPDESC_FLAGS_WC);
61457 
61458 	/*
61459 	 *  Since built-ins are not often extended, compact them.
61460 	 */
61461 
61462 	DUK_DD(DUK_DDPRINT("compact built-ins"));
61463 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61464 		duk_hobject_compact_props(thr, duk_known_hobject(thr, (duk_idx_t) i));
61465 	}
61466 
61467 	DUK_D(DUK_DPRINT("INITBUILTINS END"));
61468 
61469 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 1)
61470 	for (i = 0; i < DUK_NUM_ALL_BUILTINS; i++) {
61471 		DUK_DD(DUK_DDPRINT("built-in object %ld after initialization and compacting: %!@iO",
61472 		                   (long) i, (duk_heaphdr *) duk_require_hobject(thr, i)));
61473 	}
61474 #endif
61475 
61476 	/*
61477 	 *  Pop built-ins from stack: they are now INCREF'd and
61478 	 *  reachable from the builtins[] array or indirectly
61479 	 *  through builtins[].
61480 	 */
61481 
61482 	duk_set_top(thr, 0);
61483 	DUK_ASSERT_TOP(thr, 0);
61484 }
61485 #endif  /* DUK_USE_ROM_OBJECTS */
61486 
61487 DUK_INTERNAL void duk_hthread_copy_builtin_objects(duk_hthread *thr_from, duk_hthread *thr_to) {
61488 	duk_small_uint_t i;
61489 
61490 	for (i = 0; i < DUK_NUM_BUILTINS; i++) {
61491 		thr_to->builtins[i] = thr_from->builtins[i];
61492 		DUK_HOBJECT_INCREF_ALLOWNULL(thr_to, thr_to->builtins[i]);  /* side effect free */
61493 	}
61494 }
61495 
61496 /* automatic undefs */
61497 #undef DUK__LENGTH_PROP_BITS
61498 #undef DUK__NARGS_BITS
61499 #undef DUK__NARGS_VARARGS_MARKER
61500 #undef DUK__PROP_FLAGS_BITS
61501 #undef DUK__PROP_TYPE_ACCESSOR
61502 #undef DUK__PROP_TYPE_BITS
61503 #undef DUK__PROP_TYPE_BOOLEAN_FALSE
61504 #undef DUK__PROP_TYPE_BOOLEAN_TRUE
61505 #undef DUK__PROP_TYPE_BUILTIN
61506 #undef DUK__PROP_TYPE_DOUBLE
61507 #undef DUK__PROP_TYPE_STRIDX
61508 #undef DUK__PROP_TYPE_STRING
61509 #undef DUK__PROP_TYPE_UNDEFINED
61510 #line 1 "duk_hthread_misc.c"
61511 /*
61512  *  Thread support.
61513  */
61514 
61515 /* #include duk_internal.h -> already included */
61516 
61517 DUK_INTERNAL void duk_hthread_terminate(duk_hthread *thr) {
61518 	DUK_ASSERT(thr != NULL);
61519 
61520 	while (thr->callstack_curr != NULL) {
61521 		duk_hthread_activation_unwind_norz(thr);
61522 	}
61523 
61524 	thr->valstack_bottom = thr->valstack;
61525 	duk_set_top(thr, 0);  /* unwinds valstack, updating refcounts */
61526 
61527 	thr->state = DUK_HTHREAD_STATE_TERMINATED;
61528 
61529 	/* Here we could remove references to built-ins, but it may not be
61530 	 * worth the effort because built-ins are quite likely to be shared
61531 	 * with another (unterminated) thread, and terminated threads are also
61532 	 * usually garbage collected quite quickly.
61533 	 *
61534 	 * We could also shrink the value stack here, but that also may not
61535 	 * be worth the effort for the same reason.
61536 	 */
61537 
61538 	DUK_REFZERO_CHECK_SLOW(thr);
61539 }
61540 
61541 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61542 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_curr_pc(duk_hthread *thr, duk_activation *act) {
61543 	duk_instr_t *bcode;
61544 
61545 	DUK_ASSERT(thr != NULL);
61546 	DUK_ASSERT(act != NULL);
61547 	DUK_UNREF(thr);
61548 
61549 	/* XXX: store 'bcode' pointer to activation for faster lookup? */
61550 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
61551 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
61552 		return (duk_uint_fast32_t) (act->curr_pc - bcode);
61553 	}
61554 	return 0;
61555 }
61556 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
61557 
61558 DUK_INTERNAL duk_uint_fast32_t duk_hthread_get_act_prev_pc(duk_hthread *thr, duk_activation *act) {
61559 	duk_instr_t *bcode;
61560 	duk_uint_fast32_t ret;
61561 
61562 	DUK_ASSERT(thr != NULL);
61563 	DUK_ASSERT(act != NULL);
61564 	DUK_UNREF(thr);
61565 
61566 	if (act->func && DUK_HOBJECT_IS_COMPFUNC(act->func)) {
61567 		bcode = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) (act->func));
61568 		ret = (duk_uint_fast32_t) (act->curr_pc - bcode);
61569 		if (ret > 0) {
61570 			ret--;
61571 		}
61572 		return ret;
61573 	}
61574 	return 0;
61575 }
61576 
61577 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
61578 DUK_INTERNAL void duk_hthread_sync_currpc(duk_hthread *thr) {
61579 	duk_activation *act;
61580 
61581 	DUK_ASSERT(thr != NULL);
61582 
61583 	if (thr->ptr_curr_pc != NULL) {
61584 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
61585 		DUK_ASSERT(thr->callstack_top > 0);
61586 		DUK_ASSERT(thr->callstack_curr != NULL);
61587 		act = thr->callstack_curr;
61588 		DUK_ASSERT(act != NULL);
61589 		act->curr_pc = *thr->ptr_curr_pc;
61590 	}
61591 }
61592 
61593 DUK_INTERNAL void duk_hthread_sync_and_null_currpc(duk_hthread *thr) {
61594 	duk_activation *act;
61595 
61596 	DUK_ASSERT(thr != NULL);
61597 
61598 	if (thr->ptr_curr_pc != NULL) {
61599 		/* ptr_curr_pc != NULL only when bytecode executor is active. */
61600 		DUK_ASSERT(thr->callstack_top > 0);
61601 		DUK_ASSERT(thr->callstack_curr != NULL);
61602 		act = thr->callstack_curr;
61603 		DUK_ASSERT(act != NULL);
61604 		act->curr_pc = *thr->ptr_curr_pc;
61605 		thr->ptr_curr_pc = NULL;
61606 	}
61607 }
61608 #line 1 "duk_hthread_stacks.c"
61609 /*
61610  *  Thread stack (mainly call stack) primitives: allocation of activations,
61611  *  unwinding catchers and activations, etc.
61612  *
61613  *  Value stack handling is a part of the API implementation.
61614  */
61615 
61616 /* #include duk_internal.h -> already included */
61617 
61618 /* Unwind the topmost catcher of the current activation (caller must check that
61619  * both exist) without side effects.
61620  */
61621 DUK_INTERNAL void duk_hthread_catcher_unwind_norz(duk_hthread *thr, duk_activation *act) {
61622 	duk_catcher *cat;
61623 
61624 	DUK_ASSERT(thr != NULL);
61625 	DUK_ASSERT(act != NULL);
61626 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
61627 	cat = act->cat;
61628 	DUK_ASSERT(cat != NULL);
61629 
61630 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is done)", (void *) cat));
61631 
61632 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
61633 		duk_hobject *env;
61634 
61635 		env = act->lex_env;             /* current lex_env of the activation (created for catcher) */
61636 		DUK_ASSERT(env != NULL);        /* must be, since env was created when catcher was created */
61637 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);  /* prototype is lex_env before catcher created */
61638 		DUK_HOBJECT_INCREF(thr, act->lex_env);
61639 		DUK_HOBJECT_DECREF_NORZ(thr, env);
61640 
61641 		/* There is no need to decref anything else than 'env': if 'env'
61642 		 * becomes unreachable, refzero will handle decref'ing its prototype.
61643 		 */
61644 	}
61645 
61646 	act->cat = cat->parent;
61647 	duk_hthread_catcher_free(thr, cat);
61648 }
61649 
61650 /* Same as above, but caller is certain no catcher-related lexenv may exist. */
61651 DUK_INTERNAL void duk_hthread_catcher_unwind_nolexenv_norz(duk_hthread *thr, duk_activation *act) {
61652 	duk_catcher *cat;
61653 
61654 	DUK_ASSERT(thr != NULL);
61655 	DUK_ASSERT(act != NULL);
61656 	DUK_ASSERT(act->cat != NULL);  /* caller must check */
61657 	cat = act->cat;
61658 	DUK_ASSERT(cat != NULL);
61659 
61660 	DUK_DDD(DUK_DDDPRINT("unwinding catch stack entry %p (lexenv check is not done)", (void *) cat));
61661 
61662 	DUK_ASSERT(!DUK_CAT_HAS_LEXENV_ACTIVE(cat));
61663 
61664 	act->cat = cat->parent;
61665 	duk_hthread_catcher_free(thr, cat);
61666 }
61667 
61668 DUK_LOCAL
61669 #if defined(DUK_USE_CACHE_CATCHER)
61670 DUK_NOINLINE
61671 #endif
61672 duk_catcher *duk__hthread_catcher_alloc_slow(duk_hthread *thr) {
61673 	duk_catcher *cat;
61674 
61675 	cat = (duk_catcher *) DUK_ALLOC_CHECKED(thr, sizeof(duk_catcher));
61676 	DUK_ASSERT(cat != NULL);
61677 	return cat;
61678 }
61679 
61680 #if defined(DUK_USE_CACHE_CATCHER)
61681 DUK_INTERNAL DUK_INLINE duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
61682 	duk_catcher *cat;
61683 
61684 	DUK_ASSERT(thr != NULL);
61685 
61686 	cat = thr->heap->catcher_free;
61687 	if (DUK_LIKELY(cat != NULL)) {
61688 		thr->heap->catcher_free = cat->parent;
61689 		return cat;
61690 	}
61691 
61692 	return duk__hthread_catcher_alloc_slow(thr);
61693 }
61694 #else  /* DUK_USE_CACHE_CATCHER */
61695 DUK_INTERNAL duk_catcher *duk_hthread_catcher_alloc(duk_hthread *thr) {
61696 	return duk__hthread_catcher_alloc_slow(thr);
61697 }
61698 #endif  /* DUK_USE_CACHE_CATCHER */
61699 
61700 DUK_INTERNAL void duk_hthread_catcher_free(duk_hthread *thr, duk_catcher *cat) {
61701 	DUK_ASSERT(thr != NULL);
61702 	DUK_ASSERT(cat != NULL);
61703 
61704 #if defined(DUK_USE_CACHE_CATCHER)
61705 	/* Unconditional caching for now; freed in mark-and-sweep. */
61706 	cat->parent = thr->heap->catcher_free;
61707 	thr->heap->catcher_free = cat;
61708 #else
61709 	DUK_FREE_CHECKED(thr, (void *) cat);
61710 #endif
61711 }
61712 
61713 DUK_LOCAL
61714 #if defined(DUK_USE_CACHE_ACTIVATION)
61715 DUK_NOINLINE
61716 #endif
61717 duk_activation *duk__hthread_activation_alloc_slow(duk_hthread *thr) {
61718 	duk_activation *act;
61719 
61720 	act = (duk_activation *) DUK_ALLOC_CHECKED(thr, sizeof(duk_activation));
61721 	DUK_ASSERT(act != NULL);
61722 	return act;
61723 }
61724 
61725 #if defined(DUK_USE_CACHE_ACTIVATION)
61726 DUK_INTERNAL DUK_INLINE duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
61727 	duk_activation *act;
61728 
61729 	DUK_ASSERT(thr != NULL);
61730 
61731 	act = thr->heap->activation_free;
61732 	if (DUK_LIKELY(act != NULL)) {
61733 		thr->heap->activation_free = act->parent;
61734 		return act;
61735 	}
61736 
61737 	return duk__hthread_activation_alloc_slow(thr);
61738 }
61739 #else  /* DUK_USE_CACHE_ACTIVATION */
61740 DUK_INTERNAL duk_activation *duk_hthread_activation_alloc(duk_hthread *thr) {
61741 	return duk__hthread_activation_alloc_slow(thr);
61742 }
61743 #endif  /* DUK_USE_CACHE_ACTIVATION */
61744 
61745 
61746 DUK_INTERNAL void duk_hthread_activation_free(duk_hthread *thr, duk_activation *act) {
61747 	DUK_ASSERT(thr != NULL);
61748 	DUK_ASSERT(act != NULL);
61749 
61750 #if defined(DUK_USE_CACHE_ACTIVATION)
61751 	/* Unconditional caching for now; freed in mark-and-sweep. */
61752 	act->parent = thr->heap->activation_free;
61753 	thr->heap->activation_free = act;
61754 #else
61755 	DUK_FREE_CHECKED(thr, (void *) act);
61756 #endif
61757 }
61758 
61759 /* Internal helper: process the unwind for the topmost activation of a thread,
61760  * but leave the duk_activation in place for possible tailcall reuse.
61761  */
61762 DUK_LOCAL void duk__activation_unwind_nofree_norz(duk_hthread *thr) {
61763 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61764 	duk_heap *heap;
61765 #endif
61766 	duk_activation *act;
61767 	duk_hobject *func;
61768 	duk_hobject *tmp;
61769 
61770 	DUK_ASSERT(thr != NULL);
61771 	DUK_ASSERT(thr->callstack_curr != NULL);  /* caller must check */
61772 	DUK_ASSERT(thr->callstack_top > 0);
61773 	act = thr->callstack_curr;
61774 	DUK_ASSERT(act != NULL);
61775 	/* With lightfuncs, act 'func' may be NULL. */
61776 
61777 	/* With duk_activation records allocated separately, 'act' is a stable
61778 	 * pointer and not affected by side effects.
61779 	 */
61780 
61781 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
61782 	/*
61783 	 *  Restore 'caller' property for non-strict callee functions.
61784 	 */
61785 
61786 	func = DUK_ACT_GET_FUNC(act);
61787 	if (func != NULL && !DUK_HOBJECT_HAS_STRICT(func)) {
61788 		duk_tval *tv_caller;
61789 		duk_tval tv_tmp;
61790 		duk_hobject *h_tmp;
61791 
61792 		tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
61793 
61794 		/* The act->prev_caller should only be set if the entry for 'caller'
61795 		 * exists (as it is only set in that case, and the property is not
61796 		 * configurable), but handle all the cases anyway.
61797 		 */
61798 
61799 		if (tv_caller) {
61800 			DUK_TVAL_SET_TVAL(&tv_tmp, tv_caller);
61801 			if (act->prev_caller) {
61802 				/* Just transfer the refcount from act->prev_caller to tv_caller,
61803 				 * so no need for a refcount update.  This is the expected case.
61804 				 */
61805 				DUK_TVAL_SET_OBJECT(tv_caller, act->prev_caller);
61806 				act->prev_caller = NULL;
61807 			} else {
61808 				DUK_TVAL_SET_NULL(tv_caller);   /* no incref needed */
61809 				DUK_ASSERT(act->prev_caller == NULL);
61810 			}
61811 			DUK_TVAL_DECREF_NORZ(thr, &tv_tmp);
61812 		} else {
61813 			h_tmp = act->prev_caller;
61814 			if (h_tmp) {
61815 				act->prev_caller = NULL;
61816 				DUK_HOBJECT_DECREF_NORZ(thr, h_tmp);
61817 			}
61818 		}
61819 		DUK_ASSERT(act->prev_caller == NULL);
61820 	}
61821 #endif
61822 
61823 	/*
61824 	 *  Unwind debugger state.  If we unwind while stepping
61825 	 *  (for any step type), pause execution.  This is the
61826 	 *  only place explicitly handling a step out.
61827 	 */
61828 
61829 #if defined(DUK_USE_DEBUGGER_SUPPORT)
61830 	heap = thr->heap;
61831 	if (heap->dbg_pause_act == thr->callstack_curr) {
61832 		if (heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_EXIT) {
61833 			DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function exit"));
61834 			duk_debug_set_paused(heap);
61835 		} else {
61836 			DUK_D(DUK_DPRINT("unwound past dbg_pause_act, set to NULL"));
61837 			heap->dbg_pause_act = NULL;  /* avoid stale pointers */
61838 		}
61839 		DUK_ASSERT(heap->dbg_pause_act == NULL);
61840 	}
61841 #endif
61842 
61843 	/*
61844 	 *  Unwind catchers.
61845 	 *
61846 	 *  Since there are no references in the catcher structure,
61847 	 *  unwinding is quite simple.  The only thing we need to
61848 	 *  look out for is popping a possible lexical environment
61849 	 *  established for an active catch clause.
61850 	 */
61851 
61852 	while (act->cat != NULL) {
61853 		duk_hthread_catcher_unwind_norz(thr, act);
61854 	}
61855 
61856 	/*
61857 	 *  Close environment record(s) if they exist.
61858 	 *
61859 	 *  Only variable environments are closed.  If lex_env != var_env, it
61860 	 *  cannot currently contain any register bound declarations.
61861 	 *
61862 	 *  Only environments created for a NEWENV function are closed.  If an
61863 	 *  environment is created for e.g. an eval call, it must not be closed.
61864 	 */
61865 
61866 	func = DUK_ACT_GET_FUNC(act);
61867 	if (func != NULL && !DUK_HOBJECT_HAS_NEWENV(func)) {
61868 		DUK_DDD(DUK_DDDPRINT("skip closing environments, envs not owned by this activation"));
61869 		goto skip_env_close;
61870 	}
61871 	/* func is NULL for lightfunc */
61872 
61873 	/* Catch sites are required to clean up their environments
61874 	 * in FINALLY part before propagating, so this should
61875 	 * always hold here.
61876 	 */
61877 	DUK_ASSERT(act->lex_env == act->var_env);
61878 
61879 	/* XXX: Closing the environment record copies values from registers
61880 	 * into the scope object.  It's side effect free as such, but may
61881 	 * currently run out of memory which causes an error throw.  This is
61882 	 * an actual sandboxing problem for error unwinds, and needs to be
61883 	 * fixed e.g. by preallocating the scope property slots.
61884 	 */
61885 	if (act->var_env != NULL) {
61886 		DUK_DDD(DUK_DDDPRINT("closing var_env record %p -> %!O",
61887 		                     (void *) act->var_env, (duk_heaphdr *) act->var_env));
61888 		duk_js_close_environment_record(thr, act->var_env);
61889 	}
61890 
61891  skip_env_close:
61892 
61893 	/*
61894 	 *  Update preventcount
61895 	 */
61896 
61897 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
61898 		DUK_ASSERT(thr->callstack_preventcount >= 1);
61899 		thr->callstack_preventcount--;
61900 	}
61901 
61902 	/*
61903 	 *  Reference count updates, using NORZ macros so we don't
61904 	 *  need to handle side effects.
61905 	 *
61906 	 *  duk_activation pointers like act->var_env are intentionally
61907 	 *  left as garbage and not NULLed.  Without side effects they
61908 	 *  can't be used when the values are dangling/garbage.
61909 	 */
61910 
61911 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->var_env);
61912 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, act->lex_env);
61913 	tmp = DUK_ACT_GET_FUNC(act);
61914 	DUK_HOBJECT_DECREF_NORZ_ALLOWNULL(thr, tmp);
61915 	DUK_UNREF(tmp);
61916 }
61917 
61918 /* Unwind topmost duk_activation of a thread, caller must ensure that an
61919  * activation exists.  The call is side effect free, except that scope
61920  * closure may currently throw an out-of-memory error.
61921  */
61922 DUK_INTERNAL void duk_hthread_activation_unwind_norz(duk_hthread *thr) {
61923 	duk_activation *act;
61924 
61925 	duk__activation_unwind_nofree_norz(thr);
61926 
61927 	DUK_ASSERT(thr->callstack_curr != NULL);
61928 	DUK_ASSERT(thr->callstack_top > 0);
61929 	act = thr->callstack_curr;
61930 	thr->callstack_curr = act->parent;
61931 	thr->callstack_top--;
61932 
61933 	/* Ideally we'd restore value stack reserve here to caller's value.
61934 	 * This doesn't work for current unwind call sites however, because
61935 	 * the current (unwound) value stack top may be above the reserve.
61936 	 * Thus value stack reserve is restored by the call sites.
61937 	 */
61938 
61939 	/* XXX: inline for performance builds? */
61940 	duk_hthread_activation_free(thr, act);
61941 
61942 	/* We could clear the book-keeping variables like retval_byteoff for
61943 	 * the topmost activation, but don't do so now as it's not necessary.
61944 	 */
61945 }
61946 
61947 DUK_INTERNAL void duk_hthread_activation_unwind_reuse_norz(duk_hthread *thr) {
61948 	duk__activation_unwind_nofree_norz(thr);
61949 }
61950 
61951 /* Get duk_activation for given callstack level or NULL if level is invalid
61952  * or deeper than the call stack.  Level -1 refers to current activation, -2
61953  * to its caller, etc.  Starting from Duktape 2.2 finding the activation is
61954  * a linked list scan which gets more expensive the deeper the lookup is.
61955  */
61956 DUK_INTERNAL duk_activation *duk_hthread_get_activation_for_level(duk_hthread *thr, duk_int_t level) {
61957 	duk_activation *act;
61958 
61959 	if (level >= 0) {
61960 		return NULL;
61961 	}
61962 	act = thr->callstack_curr;
61963 	for (;;) {
61964 		if (act == NULL) {
61965 			return act;
61966 		}
61967 		if (level == -1) {
61968 			return act;
61969 		}
61970 		level++;
61971 		act = act->parent;
61972 	}
61973 	/* never here */
61974 }
61975 
61976 #if defined(DUK_USE_FINALIZER_TORTURE)
61977 DUK_INTERNAL void duk_hthread_valstack_torture_realloc(duk_hthread *thr) {
61978 	duk_size_t alloc_size;
61979 	duk_tval *new_ptr;
61980 	duk_ptrdiff_t alloc_end_off;
61981 	duk_ptrdiff_t end_off;
61982 	duk_ptrdiff_t bottom_off;
61983 	duk_ptrdiff_t top_off;
61984 
61985 	if (thr->valstack == NULL) {
61986 		DUK_D(DUK_DPRINT("skip valstack torture realloc, valstack is NULL"));
61987 		return;
61988 	}
61989 
61990 	alloc_end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_alloc_end - (duk_uint8_t *) thr->valstack);
61991 	end_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
61992 	bottom_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
61993 	top_off = (duk_ptrdiff_t) ((duk_uint8_t *) thr->valstack_top - (duk_uint8_t *) thr->valstack);
61994 	alloc_size = (duk_size_t) alloc_end_off;
61995 	if (alloc_size == 0) {
61996 		DUK_D(DUK_DPRINT("skip valstack torture realloc, alloc_size is zero"));
61997 		return;
61998 	}
61999 
62000 	/* Use DUK_ALLOC_RAW() to avoid side effects. */
62001 	new_ptr = (duk_tval *) DUK_ALLOC_RAW(thr->heap, alloc_size);
62002 	if (new_ptr != NULL) {
62003 		duk_memcpy((void *) new_ptr, (const void *) thr->valstack, alloc_size);
62004 		duk_memset((void *) thr->valstack, 0x55, alloc_size);
62005 		DUK_FREE_CHECKED(thr, (void *) thr->valstack);
62006 		thr->valstack = new_ptr;
62007 		thr->valstack_alloc_end = (duk_tval *) ((duk_uint8_t *) new_ptr + alloc_end_off);
62008 		thr->valstack_end = (duk_tval *) ((duk_uint8_t *) new_ptr + end_off);
62009 		thr->valstack_bottom = (duk_tval *) ((duk_uint8_t *) new_ptr + bottom_off);
62010 		thr->valstack_top = (duk_tval *) ((duk_uint8_t *) new_ptr + top_off);
62011 	} else {
62012 		DUK_D(DUK_DPRINT("failed to realloc valstack for torture, ignore"));
62013 	}
62014 }
62015 #endif  /* DUK_USE_FINALIZER_TORTURE */
62016 #line 1 "duk_js_arith.c"
62017 /*
62018  *  Shared helpers for arithmetic operations
62019  */
62020 
62021 /* #include duk_internal.h -> already included */
62022 
62023 /* ECMAScript modulus ('%') does not match IEEE 754 "remainder" operation
62024  * (implemented by remainder() in C99) but does seem to match ANSI C fmod().
62025  * Compare E5 Section 11.5.3 and "man fmod".
62026  */
62027 DUK_INTERNAL double duk_js_arith_mod(double d1, double d2) {
62028 #if defined(DUK_USE_POW_WORKAROUNDS)
62029 	/* Specific fixes to common fmod() implementation issues:
62030 	 * - test-bug-mingw-math-issues.js
62031 	 */
62032 	if (DUK_ISINF(d2)) {
62033 		if (DUK_ISINF(d1)) {
62034 			return DUK_DOUBLE_NAN;
62035 		} else {
62036 			return d1;
62037 		}
62038 	} else if (d1 == 0.0) {
62039 		/* d1 +/-0 is returned as is (preserving sign) except when
62040 		 * d2 is zero or NaN.
62041 		 */
62042 		if (d2 == 0.0 || DUK_ISNAN(d2)) {
62043 			return DUK_DOUBLE_NAN;
62044 		} else {
62045 			return d1;
62046 		}
62047 	}
62048 #else
62049 	/* Some ISO C assumptions. */
62050 	DUK_ASSERT(DUK_FMOD(1.0, DUK_DOUBLE_INFINITY) == 1.0);
62051 	DUK_ASSERT(DUK_FMOD(-1.0, DUK_DOUBLE_INFINITY) == -1.0);
62052 	DUK_ASSERT(DUK_FMOD(1.0, -DUK_DOUBLE_INFINITY) == 1.0);
62053 	DUK_ASSERT(DUK_FMOD(-1.0, -DUK_DOUBLE_INFINITY) == -1.0);
62054 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62055 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62056 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, DUK_DOUBLE_INFINITY)));
62057 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-DUK_DOUBLE_INFINITY, -DUK_DOUBLE_INFINITY)));
62058 	DUK_ASSERT(DUK_FMOD(0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, 1.0)) == 0);
62059 	DUK_ASSERT(DUK_FMOD(-0.0, 1.0) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, 1.0)) != 0);
62060 	DUK_ASSERT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62061 	DUK_ASSERT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, DUK_DOUBLE_INFINITY)) != 0);
62062 	DUK_ASSERT(DUK_FMOD(0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(0.0, DUK_DOUBLE_INFINITY)) == 0);
62063 	DUK_ASSERT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY) == 0.0 && DUK_SIGNBIT(DUK_FMOD(-0.0, -DUK_DOUBLE_INFINITY)) != 0);
62064 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, 0.0)));
62065 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, 0.0)));
62066 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, -0.0)));
62067 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, -0.0)));
62068 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(0.0, DUK_DOUBLE_NAN)));
62069 	DUK_ASSERT(DUK_ISNAN(DUK_FMOD(-0.0, DUK_DOUBLE_NAN)));
62070 #endif
62071 
62072 	return (duk_double_t) DUK_FMOD((double) d1, (double) d2);
62073 }
62074 
62075 /* Shared helper for Math.pow() and exponentiation operator. */
62076 DUK_INTERNAL double duk_js_arith_pow(double x, double y) {
62077 	/* The ANSI C pow() semantics differ from ECMAScript.
62078 	 *
62079 	 * E.g. when x==1 and y is +/- infinite, the ECMAScript required
62080 	 * result is NaN, while at least Linux pow() returns 1.
62081 	 */
62082 
62083 	duk_small_int_t cx, cy, sx;
62084 
62085 	DUK_UNREF(cx);
62086 	DUK_UNREF(sx);
62087 	cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
62088 
62089 	if (cy == DUK_FP_NAN) {
62090 		goto ret_nan;
62091 	}
62092 	if (DUK_FABS(x) == 1.0 && cy == DUK_FP_INFINITE) {
62093 		goto ret_nan;
62094 	}
62095 
62096 #if defined(DUK_USE_POW_WORKAROUNDS)
62097 	/* Specific fixes to common pow() implementation issues:
62098 	 *   - test-bug-netbsd-math-pow.js: NetBSD 6.0 on x86 (at least)
62099 	 *   - test-bug-mingw-math-issues.js
62100 	 */
62101 	cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
62102 	if (cx == DUK_FP_ZERO && y < 0.0) {
62103 		sx = (duk_small_int_t) DUK_SIGNBIT(x);
62104 		if (sx == 0) {
62105 			/* Math.pow(+0,y) should be Infinity when y<0.  NetBSD pow()
62106 			 * returns -Infinity instead when y is <0 and finite.  The
62107 			 * if-clause also catches y == -Infinity (which works even
62108 			 * without the fix).
62109 			 */
62110 			return DUK_DOUBLE_INFINITY;
62111 		} else {
62112 			/* Math.pow(-0,y) where y<0 should be:
62113 			 *   - -Infinity if y<0 and an odd integer
62114 			 *   - Infinity if y<0 but not an odd integer
62115 			 * NetBSD pow() returns -Infinity for all finite y<0.  The
62116 			 * if-clause also catches y == -Infinity (which works even
62117 			 * without the fix).
62118 			 */
62119 
62120 			/* fmod() return value has same sign as input (negative) so
62121 			 * the result here will be in the range ]-2,0], -1 indicates
62122 			 * odd.  If x is -Infinity, NaN is returned and the odd check
62123 			 * always concludes "not odd" which results in desired outcome.
62124 			 */
62125 			double tmp = DUK_FMOD(y, 2);
62126 			if (tmp == -1.0) {
62127 				return -DUK_DOUBLE_INFINITY;
62128 			} else {
62129 				/* Not odd, or y == -Infinity */
62130 				return DUK_DOUBLE_INFINITY;
62131 			}
62132 		}
62133 	} else if (cx == DUK_FP_NAN) {
62134 		if (y == 0.0) {
62135 			/* NaN ** +/- 0 should always be 1, but is NaN on
62136 			 * at least some Cygwin/MinGW versions.
62137 			 */
62138 			return 1.0;
62139 		}
62140 	}
62141 #else
62142 	/* Some ISO C assumptions. */
62143 	DUK_ASSERT(DUK_POW(DUK_DOUBLE_NAN, 0.0) == 1.0);
62144 	DUK_ASSERT(DUK_ISINF(DUK_POW(0.0, -1.0)) && DUK_SIGNBIT(DUK_POW(0.0, -1.0)) == 0);
62145 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -2.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -2.0)) == 0);
62146 	DUK_ASSERT(DUK_ISINF(DUK_POW(-0.0, -3.0)) && DUK_SIGNBIT(DUK_POW(-0.0, -3.0)) != 0);
62147 #endif
62148 
62149 	return DUK_POW(x, y);
62150 
62151  ret_nan:
62152 	return DUK_DOUBLE_NAN;
62153 }
62154 #line 1 "duk_js_call.c"
62155 /*
62156  *  Call handling.
62157  *
62158  *  duk_handle_call_unprotected():
62159  *
62160  *    - Unprotected call to ECMAScript or Duktape/C function, from native
62161  *      code or bytecode executor.
62162  *
62163  *    - Also handles Ecma-to-Ecma calls which reuses a currently running
62164  *      executor instance to avoid native recursion.  Call setup is done
62165  *      normally, but just before calling the bytecode executor a special
62166  *      return code is used to indicate that a calling executor is reused.
62167  *
62168  *    - Also handles tailcalls, i.e. reuse of current duk_activation.
62169  *
62170  *    - Also handles setup for initial Duktape.Thread.resume().
62171  *
62172  *  duk_handle_safe_call():
62173  *
62174  *    - Protected C call within current activation.
62175  *
62176  *  setjmp() and local variables have a nasty interaction, see execution.rst;
62177  *  non-volatile locals modified after setjmp() call are not guaranteed to
62178  *  keep their value and can cause compiler or compiler version specific
62179  *  difficult to replicate issues.
62180  *
62181  *  See 'execution.rst'.
62182  */
62183 
62184 /* #include duk_internal.h -> already included */
62185 
62186 /* XXX: heap->error_not_allowed for success path too? */
62187 
62188 /*
62189  *  Limit check helpers.
62190  */
62191 
62192 /* Allow headroom for calls during error augmentation (see GH-191).
62193  * We allow space for 10 additional recursions, with one extra
62194  * for, e.g. a print() call at the deepest level, and an extra
62195  * +1 for protected call wrapping.
62196  */
62197 #define DUK__AUGMENT_CALL_RELAX_COUNT  (10 + 2)
62198 
62199 DUK_LOCAL DUK_NOINLINE void duk__call_c_recursion_limit_check_slowpath(duk_hthread *thr) {
62200 	/* When augmenting an error, the effective limit is a bit higher.
62201 	 * Check for it only if the fast path check fails.
62202 	 */
62203 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62204 	if (thr->heap->augmenting_error) {
62205 		if (thr->heap->call_recursion_depth < thr->heap->call_recursion_limit + DUK__AUGMENT_CALL_RELAX_COUNT) {
62206 			DUK_D(DUK_DPRINT("C recursion limit reached but augmenting error and within relaxed limit"));
62207 			return;
62208 		}
62209 	}
62210 #endif
62211 
62212 	DUK_D(DUK_DPRINT("call prevented because C recursion limit reached"));
62213 	DUK_ERROR_RANGE(thr, DUK_STR_C_CALLSTACK_LIMIT);
62214 	DUK_WO_NORETURN(return;);
62215 }
62216 
62217 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_c_recursion_limit_check(duk_hthread *thr) {
62218 	DUK_ASSERT(thr->heap->call_recursion_depth >= 0);
62219 	DUK_ASSERT(thr->heap->call_recursion_depth <= thr->heap->call_recursion_limit);
62220 
62221 	/* This check is forcibly inlined because it's very cheap and almost
62222 	 * always passes.  The slow path is forcibly noinline.
62223 	 */
62224 	if (DUK_LIKELY(thr->heap->call_recursion_depth < thr->heap->call_recursion_limit)) {
62225 		return;
62226 	}
62227 
62228 	duk__call_c_recursion_limit_check_slowpath(thr);
62229 }
62230 
62231 DUK_LOCAL DUK_NOINLINE void duk__call_callstack_limit_check_slowpath(duk_hthread *thr) {
62232 	/* When augmenting an error, the effective limit is a bit higher.
62233 	 * Check for it only if the fast path check fails.
62234 	 */
62235 #if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
62236 	if (thr->heap->augmenting_error) {
62237 		if (thr->callstack_top < DUK_USE_CALLSTACK_LIMIT + DUK__AUGMENT_CALL_RELAX_COUNT) {
62238 			DUK_D(DUK_DPRINT("call stack limit reached but augmenting error and within relaxed limit"));
62239 			return;
62240 		}
62241 	}
62242 #endif
62243 
62244 	/* XXX: error message is a bit misleading: we reached a recursion
62245 	 * limit which is also essentially the same as a C callstack limit
62246 	 * (except perhaps with some relaxed threading assumptions).
62247 	 */
62248 	DUK_D(DUK_DPRINT("call prevented because call stack limit reached"));
62249 	DUK_ERROR_RANGE(thr, DUK_STR_CALLSTACK_LIMIT);
62250 	DUK_WO_NORETURN(return;);
62251 }
62252 
62253 DUK_LOCAL DUK_ALWAYS_INLINE void duk__call_callstack_limit_check(duk_hthread *thr) {
62254 	/* This check is forcibly inlined because it's very cheap and almost
62255 	 * always passes.  The slow path is forcibly noinline.
62256 	 */
62257 	if (DUK_LIKELY(thr->callstack_top < DUK_USE_CALLSTACK_LIMIT)) {
62258 		return;
62259 	}
62260 
62261 	duk__call_callstack_limit_check_slowpath(thr);
62262 }
62263 
62264 /*
62265  *  Interrupt counter fixup (for development only).
62266  */
62267 
62268 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
62269 DUK_LOCAL void duk__interrupt_fixup(duk_hthread *thr, duk_hthread *entry_curr_thread) {
62270 	/* Currently the bytecode executor and executor interrupt
62271 	 * instruction counts are off because we don't execute the
62272 	 * interrupt handler when we're about to exit from the initial
62273 	 * user call into Duktape.
62274 	 *
62275 	 * If we were to execute the interrupt handler here, the counts
62276 	 * would match.  You can enable this block manually to check
62277 	 * that this is the case.
62278 	 */
62279 
62280 	DUK_ASSERT(thr != NULL);
62281 	DUK_ASSERT(thr->heap != NULL);
62282 
62283 #if defined(DUK_USE_INTERRUPT_DEBUG_FIXUP)
62284 	if (entry_curr_thread == NULL) {
62285 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
62286 		thr->heap->inst_count_interrupt += thr->interrupt_init;
62287 		DUK_DD(DUK_DDPRINT("debug test: updated interrupt count on exit to "
62288 		                   "user code, instruction counts: executor=%ld, interrupt=%ld",
62289 		                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
62290 		DUK_ASSERT(thr->heap->inst_count_exec == thr->heap->inst_count_interrupt);
62291 	}
62292 #else
62293 	DUK_UNREF(thr);
62294 	DUK_UNREF(entry_curr_thread);
62295 #endif
62296 }
62297 #endif
62298 
62299 /*
62300  *  Arguments object creation.
62301  *
62302  *  Creating arguments objects involves many small details, see E5 Section
62303  *  10.6 for the specific requirements.  Much of the arguments object exotic
62304  *  behavior is implemented in duk_hobject_props.c, and is enabled by the
62305  *  object flag DUK_HOBJECT_FLAG_EXOTIC_ARGUMENTS.
62306  */
62307 
62308 DUK_LOCAL void duk__create_arguments_object(duk_hthread *thr,
62309                                             duk_hobject *func,
62310                                             duk_hobject *varenv,
62311                                             duk_idx_t idx_args) {
62312 	duk_hobject *arg;          /* 'arguments' */
62313 	duk_hobject *formals;      /* formals for 'func' (may be NULL if func is a C function) */
62314 	duk_idx_t i_arg;
62315 	duk_idx_t i_map;
62316 	duk_idx_t i_mappednames;
62317 	duk_idx_t i_formals;
62318 	duk_idx_t i_argbase;
62319 	duk_idx_t n_formals;
62320 	duk_idx_t idx;
62321 	duk_idx_t num_stack_args;
62322 	duk_bool_t need_map;
62323 
62324 	DUK_ASSERT(thr != NULL);
62325 	DUK_ASSERT(func != NULL);
62326 	DUK_ASSERT(DUK_HOBJECT_IS_NONBOUND_FUNCTION(func));
62327 	DUK_ASSERT(varenv != NULL);
62328 
62329 	/* [ ... func this arg1(@idx_args) ... argN envobj ]
62330 	 * [ arg1(@idx_args) ... argN envobj ] (for tailcalls)
62331 	 */
62332 
62333 	need_map = 0;
62334 
62335 	i_argbase = idx_args;
62336 	num_stack_args = duk_get_top(thr) - i_argbase - 1;
62337 	DUK_ASSERT(i_argbase >= 0);
62338 	DUK_ASSERT(num_stack_args >= 0);
62339 
62340 	duk_push_hobject(thr, func);
62341 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS);
62342 	formals = duk_get_hobject(thr, -1);
62343 	if (formals) {
62344 		n_formals = (duk_idx_t) duk_get_length(thr, -1);
62345 	} else {
62346 		/* This shouldn't happen without tampering of internal
62347 		 * properties: if a function accesses 'arguments', _Formals
62348 		 * is kept.  Check for the case anyway in case internal
62349 		 * properties have been modified manually.
62350 		 */
62351 		DUK_D(DUK_DPRINT("_Formals is undefined when creating arguments, use n_formals == 0"));
62352 		n_formals = 0;
62353 	}
62354 	duk_remove_m2(thr);  /* leave formals on stack for later use */
62355 	i_formals = duk_require_top_index(thr);
62356 
62357 	DUK_ASSERT(n_formals >= 0);
62358 	DUK_ASSERT(formals != NULL || n_formals == 0);
62359 
62360 	DUK_DDD(DUK_DDDPRINT("func=%!O, formals=%!O, n_formals=%ld",
62361 	                     (duk_heaphdr *) func, (duk_heaphdr *) formals,
62362 	                     (long) n_formals));
62363 
62364 	/* [ ... formals ] */
62365 
62366 	/*
62367 	 *  Create required objects:
62368 	 *    - 'arguments' object: array-like, but not an array
62369 	 *    - 'map' object: internal object, tied to 'arguments'
62370 	 *    - 'mappedNames' object: temporary value used during construction
62371 	 */
62372 
62373 	arg = duk_push_object_helper(thr,
62374 	                             DUK_HOBJECT_FLAG_EXTENSIBLE |
62375 	                             DUK_HOBJECT_FLAG_FASTREFS |
62376 	                             DUK_HOBJECT_FLAG_ARRAY_PART |
62377 	                             DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_ARGUMENTS),
62378 	                             DUK_BIDX_OBJECT_PROTOTYPE);
62379 	DUK_ASSERT(arg != NULL);
62380 	(void) duk_push_object_helper(thr,
62381 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62382 	                              DUK_HOBJECT_FLAG_FASTREFS |
62383 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62384 	                              -1);  /* no prototype */
62385 	(void) duk_push_object_helper(thr,
62386 	                              DUK_HOBJECT_FLAG_EXTENSIBLE |
62387 	                              DUK_HOBJECT_FLAG_FASTREFS |
62388 	                              DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
62389 	                              -1);  /* no prototype */
62390 	i_arg = duk_get_top(thr) - 3;
62391 	i_map = i_arg + 1;
62392 	i_mappednames = i_arg + 2;
62393 
62394 	/* [ ... formals arguments map mappedNames ] */
62395 
62396 	DUK_DDD(DUK_DDDPRINT("created arguments related objects: "
62397 	                     "arguments at index %ld -> %!O "
62398 	                     "map at index %ld -> %!O "
62399 	                     "mappednames at index %ld -> %!O",
62400 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
62401 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
62402 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
62403 
62404 	/*
62405 	 *  Init arguments properties, map, etc.
62406 	 */
62407 
62408 	duk_push_int(thr, num_stack_args);
62409 	duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_WC);
62410 
62411 	/*
62412 	 *  Init argument related properties.
62413 	 */
62414 
62415 	/* step 11 */
62416 	idx = num_stack_args - 1;
62417 	while (idx >= 0) {
62418 		DUK_DDD(DUK_DDDPRINT("arg idx %ld, argbase=%ld, argidx=%ld",
62419 		                     (long) idx, (long) i_argbase, (long) (i_argbase + idx)));
62420 
62421 		DUK_DDD(DUK_DDDPRINT("define arguments[%ld]=arg", (long) idx));
62422 		duk_dup(thr, i_argbase + idx);
62423 		duk_xdef_prop_index_wec(thr, i_arg, (duk_uarridx_t) idx);
62424 		DUK_DDD(DUK_DDDPRINT("defined arguments[%ld]=arg", (long) idx));
62425 
62426 		/* step 11.c is relevant only if non-strict (checked in 11.c.ii) */
62427 		if (!DUK_HOBJECT_HAS_STRICT(func) && idx < n_formals) {
62428 			DUK_ASSERT(formals != NULL);
62429 
62430 			DUK_DDD(DUK_DDDPRINT("strict function, index within formals (%ld < %ld)",
62431 			                     (long) idx, (long) n_formals));
62432 
62433 			duk_get_prop_index(thr, i_formals, (duk_uarridx_t) idx);
62434 			DUK_ASSERT(duk_is_string(thr, -1));
62435 
62436 			duk_dup_top(thr);  /* [ ... name name ] */
62437 
62438 			if (!duk_has_prop(thr, i_mappednames)) {
62439 				/* steps 11.c.ii.1 - 11.c.ii.4, but our internal book-keeping
62440 				 * differs from the reference model
62441 				 */
62442 
62443 				/* [ ... name ] */
62444 
62445 				need_map = 1;
62446 
62447 				DUK_DDD(DUK_DDDPRINT("set mappednames[%s]=%ld",
62448 				                     (const char *) duk_get_string(thr, -1),
62449 				                     (long) idx));
62450 				duk_dup_top(thr);                      /* name */
62451 				(void) duk_push_uint_to_hstring(thr, (duk_uint_t) idx);  /* index */
62452 				duk_xdef_prop_wec(thr, i_mappednames);  /* out of spec, must be configurable */
62453 
62454 				DUK_DDD(DUK_DDDPRINT("set map[%ld]=%s",
62455 				                     (long) idx,
62456 				                     duk_get_string(thr, -1)));
62457 				duk_dup_top(thr);         /* name */
62458 				duk_xdef_prop_index_wec(thr, i_map, (duk_uarridx_t) idx);  /* out of spec, must be configurable */
62459 			} else {
62460 				/* duk_has_prop() popped the second 'name' */
62461 			}
62462 
62463 			/* [ ... name ] */
62464 			duk_pop(thr);  /* pop 'name' */
62465 		}
62466 
62467 		idx--;
62468 	}
62469 
62470 	DUK_DDD(DUK_DDDPRINT("actual arguments processed"));
62471 
62472 	/* step 12 */
62473 	if (need_map) {
62474 		DUK_DDD(DUK_DDDPRINT("adding 'map' and 'varenv' to arguments object"));
62475 
62476 		/* should never happen for a strict callee */
62477 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
62478 
62479 		duk_dup(thr, i_map);
62480 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_MAP, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
62481 
62482 		/* The variable environment for magic variable bindings needs to be
62483 		 * given by the caller and recorded in the arguments object.
62484 		 *
62485 		 * See E5 Section 10.6, the creation of setters/getters.
62486 		 *
62487 		 * The variable environment also provides access to the callee, so
62488 		 * an explicit (internal) callee property is not needed.
62489 		 */
62490 
62491 		duk_push_hobject(thr, varenv);
62492 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_INT_VARENV, DUK_PROPDESC_FLAGS_NONE);  /* out of spec, don't care */
62493 	}
62494 
62495 	/* steps 13-14 */
62496 	if (DUK_HOBJECT_HAS_STRICT(func)) {
62497 		/* Callee/caller are throwers and are not deletable etc.  They
62498 		 * could be implemented as virtual properties, but currently
62499 		 * there is no support for virtual properties which are accessors
62500 		 * (only plain virtual properties).  This would not be difficult
62501 		 * to change in duk_hobject_props, but we can make the throwers
62502 		 * normal, concrete properties just as easily.
62503 		 *
62504 		 * Note that the specification requires that the *same* thrower
62505 		 * built-in object is used here!  See E5 Section 10.6 main
62506 		 * algoritm, step 14, and Section 13.2.3 which describes the
62507 		 * thrower.  See test case test-arguments-throwers.js.
62508 		 */
62509 
62510 		DUK_DDD(DUK_DDDPRINT("strict function, setting caller/callee to throwers"));
62511 
62512 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLER);
62513 		duk_xdef_prop_stridx_thrower(thr, i_arg, DUK_STRIDX_CALLEE);
62514 	} else {
62515 		DUK_DDD(DUK_DDDPRINT("non-strict function, setting callee to actual value"));
62516 		duk_push_hobject(thr, func);
62517 		duk_xdef_prop_stridx(thr, i_arg, DUK_STRIDX_CALLEE, DUK_PROPDESC_FLAGS_WC);
62518 	}
62519 
62520 	/* set exotic behavior only after we're done */
62521 	if (need_map) {
62522 		/* Exotic behaviors are only enabled for arguments objects
62523 		 * which have a parameter map (see E5 Section 10.6 main
62524 		 * algorithm, step 12).
62525 		 *
62526 		 * In particular, a non-strict arguments object with no
62527 		 * mapped formals does *NOT* get exotic behavior, even
62528 		 * for e.g. "caller" property.  This seems counterintuitive
62529 		 * but seems to be the case.
62530 		 */
62531 
62532 		/* cannot be strict (never mapped variables) */
62533 		DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(func));
62534 
62535 		DUK_DDD(DUK_DDDPRINT("enabling exotic behavior for arguments object"));
62536 		DUK_HOBJECT_SET_EXOTIC_ARGUMENTS(arg);
62537 	} else {
62538 		DUK_DDD(DUK_DDDPRINT("not enabling exotic behavior for arguments object"));
62539 	}
62540 
62541 	DUK_DDD(DUK_DDDPRINT("final arguments related objects: "
62542 	                     "arguments at index %ld -> %!O "
62543 	                     "map at index %ld -> %!O "
62544 	                     "mappednames at index %ld -> %!O",
62545 	                     (long) i_arg, (duk_heaphdr *) duk_get_hobject(thr, i_arg),
62546 	                     (long) i_map, (duk_heaphdr *) duk_get_hobject(thr, i_map),
62547 	                     (long) i_mappednames, (duk_heaphdr *) duk_get_hobject(thr, i_mappednames)));
62548 
62549 	/* [ args(n) envobj formals arguments map mappednames ] */
62550 
62551 	duk_pop_2(thr);
62552 	duk_remove_m2(thr);
62553 
62554 	/* [ args(n) envobj arguments ] */
62555 }
62556 
62557 /* Helper for creating the arguments object and adding it to the env record
62558  * on top of the value stack.
62559  */
62560 DUK_LOCAL void duk__handle_createargs_for_call(duk_hthread *thr,
62561                                                duk_hobject *func,
62562                                                duk_hobject *env,
62563                                                duk_idx_t idx_args) {
62564 	DUK_DDD(DUK_DDDPRINT("creating arguments object for function call"));
62565 
62566 	DUK_ASSERT(thr != NULL);
62567 	DUK_ASSERT(func != NULL);
62568 	DUK_ASSERT(env != NULL);
62569 	DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
62570 
62571 	/* [ ... arg1 ... argN envobj ] */
62572 
62573 	duk__create_arguments_object(thr,
62574 	                             func,
62575 	                             env,
62576 	                             idx_args);
62577 
62578 	/* [ ... arg1 ... argN envobj argobj ] */
62579 
62580 	duk_xdef_prop_stridx_short(thr,
62581 	                           -2,
62582 	                           DUK_STRIDX_LC_ARGUMENTS,
62583 	                           DUK_HOBJECT_HAS_STRICT(func) ? DUK_PROPDESC_FLAGS_E :   /* strict: non-deletable, non-writable */
62584 	                                                          DUK_PROPDESC_FLAGS_WE);  /* non-strict: non-deletable, writable */
62585 	/* [ ... arg1 ... argN envobj ] */
62586 }
62587 
62588 /*
62589  *  Helpers for constructor call handling.
62590  *
62591  *  There are two [[Construct]] operations in the specification:
62592  *
62593  *    - E5 Section 13.2.2: for Function objects
62594  *    - E5 Section 15.3.4.5.2: for "bound" Function objects
62595  *
62596  *  The chain of bound functions is resolved in Section 15.3.4.5.2,
62597  *  with arguments "piling up" until the [[Construct]] internal
62598  *  method is called on the final, actual Function object.  Note
62599  *  that the "prototype" property is looked up *only* from the
62600  *  final object, *before* calling the constructor.
62601  *
62602  *  Since Duktape 2.2 bound functions are represented with the
62603  *  duk_hboundfunc internal type, and bound function chains are
62604  *  collapsed when a bound function is created.  As a result, the
62605  *  direct target of a duk_hboundfunc is always non-bound and the
62606  *  this/argument lists have been resolved.
62607  *
62608  *  When constructing new Array instances, an unnecessary object is
62609  *  created and discarded now: the standard [[Construct]] creates an
62610  *  object, and calls the Array constructor.  The Array constructor
62611  *  returns an Array instance, which is used as the result value for
62612  *  the "new" operation; the object created before the Array constructor
62613  *  call is discarded.
62614  *
62615  *  This would be easy to fix, e.g. by knowing that the Array constructor
62616  *  will always create a replacement object and skip creating the fallback
62617  *  object in that case.
62618  */
62619 
62620 /* Update default instance prototype for constructor call. */
62621 DUK_LOCAL void duk__update_default_instance_proto(duk_hthread *thr, duk_idx_t idx_func) {
62622 	duk_hobject *proto;
62623 	duk_hobject *fallback;
62624 
62625 	DUK_ASSERT(duk_is_constructable(thr, idx_func));
62626 
62627 	duk_get_prop_stridx_short(thr, idx_func, DUK_STRIDX_PROTOTYPE);
62628 	proto = duk_get_hobject(thr, -1);
62629 	if (proto == NULL) {
62630 		DUK_DDD(DUK_DDDPRINT("constructor has no 'prototype' property, or value not an object "
62631 		                     "-> leave standard Object prototype as fallback prototype"));
62632 	} else {
62633 		DUK_DDD(DUK_DDDPRINT("constructor has 'prototype' property with object value "
62634 		                     "-> set fallback prototype to that value: %!iO", (duk_heaphdr *) proto));
62635 		/* Original fallback (default instance) is untouched when
62636 		 * resolving bound functions etc.
62637 		 */
62638 		fallback = duk_known_hobject(thr, idx_func + 1);
62639 		DUK_ASSERT(fallback != NULL);
62640 		DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, fallback, proto);
62641 	}
62642 	duk_pop(thr);
62643 }
62644 
62645 /* Postprocess: return value special handling, error augmentation. */
62646 DUK_INTERNAL void duk_call_construct_postprocess(duk_hthread *thr, duk_small_uint_t proxy_invariant) {
62647 	/* Use either fallback (default instance) or retval depending
62648 	 * on retval type.  Needs to be called before unwind because
62649 	 * the default instance is read from the current (immutable)
62650 	 * 'this' binding.
62651 	 *
62652 	 * For Proxy 'construct' calls the return value must be an
62653 	 * Object (we accept object-like values like buffers and
62654 	 * lightfuncs too).  If not, TypeError.
62655 	 */
62656 	if (duk_check_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT |
62657 	                                 DUK_TYPE_MASK_BUFFER |
62658 	                                 DUK_TYPE_MASK_LIGHTFUNC)) {
62659 		DUK_DDD(DUK_DDDPRINT("replacement value"));
62660 	} else {
62661 		if (DUK_UNLIKELY(proxy_invariant != 0U)) {
62662 			/* Proxy 'construct' return value invariant violated. */
62663 			DUK_ERROR_TYPE_INVALID_TRAP_RESULT(thr);
62664 			DUK_WO_NORETURN(return;);
62665 		}
62666 		/* XXX: direct value stack access */
62667 		duk_pop(thr);
62668 		duk_push_this(thr);
62669 	}
62670 
62671 #if defined(DUK_USE_AUGMENT_ERROR_CREATE)
62672 	/* Augment created errors upon creation, not when they are thrown or
62673 	 * rethrown.  __FILE__ and __LINE__ are not desirable here; the call
62674 	 * stack reflects the caller which is correct.  Skip topmost, unwound
62675 	 * activation when creating a traceback.  If thr->ptr_curr_pc was !=
62676 	 * NULL we'd need to sync the current PC so that the traceback comes
62677 	 * out right; however it is always synced here so just assert for it.
62678 	 */
62679 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
62680 	duk_err_augment_error_create(thr, thr, NULL, 0, DUK_AUGMENT_FLAG_NOBLAME_FILELINE |
62681 	                                                DUK_AUGMENT_FLAG_SKIP_ONE);
62682 #endif
62683 }
62684 
62685 /*
62686  *  Helper for handling a bound function when a call is being made.
62687  *
62688  *  Assumes that bound function chains have been "collapsed" so that either
62689  *  the target is non-bound or there is one bound function that points to a
62690  *  nonbound target.
62691  *
62692  *  Prepends the bound arguments to the value stack (at idx_func + 2).
62693  *  The 'this' binding is also updated if necessary (at idx_func + 1).
62694  *  Note that for constructor calls the 'this' binding is never updated by
62695  *  [[BoundThis]].
62696  */
62697 
62698 DUK_LOCAL void duk__handle_bound_chain_for_call(duk_hthread *thr,
62699                                                 duk_idx_t idx_func,
62700                                                 duk_bool_t is_constructor_call) {
62701 	duk_tval *tv_func;
62702 	duk_hobject *func;
62703 	duk_idx_t len;
62704 
62705 	DUK_ASSERT(thr != NULL);
62706 
62707 	/* On entry, item at idx_func is a bound, non-lightweight function,
62708 	 * but we don't rely on that below.
62709 	 */
62710 
62711 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62712 
62713 	tv_func = duk_require_tval(thr, idx_func);
62714 	DUK_ASSERT(tv_func != NULL);
62715 
62716 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
62717 		func = DUK_TVAL_GET_OBJECT(tv_func);
62718 
62719 		/* XXX: separate helper function, out of fast path? */
62720 		if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
62721 			duk_hboundfunc *h_bound;
62722 			duk_tval *tv_args;
62723 			duk_tval *tv_gap;
62724 
62725 			h_bound = (duk_hboundfunc *) (void *) func;
62726 			tv_args = h_bound->args;
62727 			len = h_bound->nargs;
62728 			DUK_ASSERT(len == 0 || tv_args != NULL);
62729 
62730 			DUK_DDD(DUK_DDDPRINT("bound function encountered, ptr=%p: %!T",
62731 			                     (void *) DUK_TVAL_GET_OBJECT(tv_func), tv_func));
62732 
62733 			/* [ ... func this arg1 ... argN ] */
62734 
62735 			if (is_constructor_call) {
62736 				/* See: tests/ecmascript/test-spec-bound-constructor.js */
62737 				DUK_DDD(DUK_DDDPRINT("constructor call: don't update this binding"));
62738 			} else {
62739 				/* XXX: duk_replace_tval */
62740 				duk_push_tval(thr, &h_bound->this_binding);
62741 				duk_replace(thr, idx_func + 1);  /* idx_this = idx_func + 1 */
62742 			}
62743 
62744 			/* [ ... func this arg1 ... argN ] */
62745 
62746 			duk_require_stack(thr, len);
62747 
62748 			tv_gap = duk_reserve_gap(thr, idx_func + 2, len);
62749 			duk_copy_tvals_incref(thr, tv_gap, tv_args, (duk_size_t) len);
62750 
62751 			/* [ ... func this <bound args> arg1 ... argN ] */
62752 
62753 			duk_push_tval(thr, &h_bound->target);
62754 			duk_replace(thr, idx_func);  /* replace in stack */
62755 
62756 			DUK_DDD(DUK_DDDPRINT("bound function handled, idx_func=%ld, curr func=%!T",
62757 			                     (long) idx_func, duk_get_tval(thr, idx_func)));
62758 		}
62759 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
62760 		/* Lightweight function: never bound, so terminate. */
62761 		;
62762 	} else {
62763 		/* Shouldn't happen, so ugly error is enough. */
62764 		DUK_ERROR_INTERNAL(thr);
62765 		DUK_WO_NORETURN(return;);
62766 	}
62767 
62768 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62769 
62770 	DUK_DDD(DUK_DDDPRINT("final non-bound function is: %!T", duk_get_tval(thr, idx_func)));
62771 
62772 #if defined(DUK_USE_ASSERTIONS)
62773 	tv_func = duk_require_tval(thr, idx_func);
62774 	DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func) || DUK_TVAL_IS_OBJECT(tv_func));
62775 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
62776 		func = DUK_TVAL_GET_OBJECT(tv_func);
62777 		DUK_ASSERT(func != NULL);
62778 		DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
62779 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func) ||
62780 		           DUK_HOBJECT_HAS_NATFUNC(func));
62781 	}
62782 #endif
62783 }
62784 
62785 /*
62786  *  Helper for inline handling of .call(), .apply(), and .construct().
62787  */
62788 
62789 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) {
62790 #if defined(DUK_USE_ASSERTIONS)
62791 	duk_c_function natfunc;
62792 #endif
62793 	duk_tval *tv_args;
62794 
62795 	DUK_ASSERT(func != NULL);
62796 	DUK_ASSERT((*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0);  /* Caller. */
62797 
62798 #if defined(DUK_USE_ASSERTIONS)
62799 	natfunc = ((duk_hnatfunc *) func)->func;
62800 	DUK_ASSERT(natfunc != NULL);
62801 #endif
62802 
62803 	/* On every round of function resolution at least target function and
62804 	 * 'this' binding are set.  We can assume that here, and must guarantee
62805 	 * it on exit.  Value stack reserve is extended for bound function and
62806 	 * .apply() unpacking so we don't need to extend it here when we need a
62807 	 * few slots.
62808 	 */
62809 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62810 
62811 	/* Handle native 'eval' specially.  A direct eval check is only made
62812 	 * for the first resolution attempt; e.g. a bound eval call is -not-
62813 	 * a direct eval call.
62814 	 */
62815 	if (DUK_UNLIKELY(((duk_hnatfunc *) func)->magic == 15)) {
62816 		/* For now no special handling except for direct eval
62817 		 * detection.
62818 		 */
62819 		DUK_ASSERT(((duk_hnatfunc *) func)->func == duk_bi_global_object_eval);
62820 		if (first && (*call_flags & DUK_CALL_FLAG_CALLED_AS_EVAL)) {
62821 			*call_flags = (*call_flags & ~DUK_CALL_FLAG_CALLED_AS_EVAL) | DUK_CALL_FLAG_DIRECT_EVAL;
62822 		}
62823 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62824 		return 1;  /* stop resolving */
62825 	}
62826 
62827 	/* Handle special functions based on the DUK_HOBJECT_FLAG_SPECIAL_CALL
62828 	 * flag; their magic value is used for switch-case.
62829 	 *
62830 	 * NOTE: duk_unpack_array_like() reserves value stack space
62831 	 * for the result values (unlike most other value stack calls).
62832 	 */
62833 	switch (((duk_hnatfunc *) func)->magic) {
62834 	case 0: {  /* 0=Function.prototype.call() */
62835 		/* Value stack:
62836 		 * idx_func + 0: Function.prototype.call()  [removed]
62837 		 * idx_func + 1: this binding for .call (target function)
62838 		 * idx_func + 2: 1st argument to .call, desired 'this' binding
62839 		 * idx_func + 3: 2nd argument to .call, desired 1st argument for ultimate target
62840 		 * ...
62841 		 *
62842 		 * Remove idx_func + 0 to get:
62843 		 * idx_func + 0: target function
62844 		 * idx_func + 1: this binding
62845 		 * idx_func + 2: call arguments
62846 		 * ...
62847 		 */
62848 		DUK_ASSERT(natfunc == duk_bi_function_prototype_call);
62849 		duk_remove_unsafe(thr, idx_func);
62850 		tv_args = thr->valstack_bottom + idx_func + 2;
62851 		if (thr->valstack_top < tv_args) {
62852 			DUK_ASSERT(tv_args <= thr->valstack_end);
62853 			thr->valstack_top = tv_args;  /* at least target function and 'this' binding present */
62854 		}
62855 		break;
62856 	}
62857 	case 1: {  /* 1=Function.prototype.apply() */
62858 		/* Value stack:
62859 		 * idx_func + 0: Function.prototype.apply()  [removed]
62860 		 * idx_func + 1: this binding for .apply (target function)
62861 		 * idx_func + 2: 1st argument to .apply, desired 'this' binding
62862 		 * idx_func + 3: 2nd argument to .apply, argArray
62863 		 * [anything after this MUST be ignored]
62864 		 *
62865 		 * Remove idx_func + 0 and unpack the argArray to get:
62866 		 * idx_func + 0: target function
62867 		 * idx_func + 1: this binding
62868 		 * idx_func + 2: call arguments
62869 		 * ...
62870 		 */
62871 		DUK_ASSERT(natfunc == duk_bi_function_prototype_apply);
62872 		duk_remove_unsafe(thr, idx_func);
62873 		goto apply_shared;
62874 	}
62875 #if defined(DUK_USE_REFLECT_BUILTIN)
62876 	case 2: {  /* 2=Reflect.apply() */
62877 		/* Value stack:
62878 		 * idx_func + 0: Reflect.apply()  [removed]
62879 		 * idx_func + 1: this binding for .apply (ignored, usually Reflect)  [removed]
62880 		 * idx_func + 2: 1st argument to .apply, target function
62881 		 * idx_func + 3: 2nd argument to .apply, desired 'this' binding
62882 		 * idx_func + 4: 3rd argument to .apply, argArray
62883 		 * [anything after this MUST be ignored]
62884 		 *
62885 		 * Remove idx_func + 0 and idx_func + 1, and unpack the argArray to get:
62886 		 * idx_func + 0: target function
62887 		 * idx_func + 1: this binding
62888 		 * idx_func + 2: call arguments
62889 		 * ...
62890 		 */
62891 		DUK_ASSERT(natfunc == duk_bi_reflect_apply);
62892 		duk_remove_n_unsafe(thr, idx_func, 2);
62893 		goto apply_shared;
62894 	}
62895 	case 3: {  /* 3=Reflect.construct() */
62896 		/* Value stack:
62897 		 * idx_func + 0: Reflect.construct()  [removed]
62898 		 * idx_func + 1: this binding for .construct (ignored, usually Reflect)  [removed]
62899 		 * idx_func + 2: 1st argument to .construct, target function
62900 		 * idx_func + 3: 2nd argument to .construct, argArray
62901 		 * idx_func + 4: 3rd argument to .construct, newTarget
62902 		 * [anything after this MUST be ignored]
62903 		 *
62904 		 * Remove idx_func + 0 and idx_func + 1, unpack the argArray,
62905 		 * and insert default instance (prototype not yet updated), to get:
62906 		 * idx_func + 0: target function
62907 		 * idx_func + 1: this binding (default instance)
62908 		 * idx_func + 2: constructor call arguments
62909 		 * ...
62910 		 *
62911 		 * Call flags must be updated to reflect the fact that we're
62912 		 * now dealing with a constructor call, and e.g. the 'this'
62913 		 * binding cannot be overwritten if the target is bound.
62914 		 *
62915 		 * newTarget is checked but not yet passed onwards.
62916 		 */
62917 
62918 		duk_idx_t top;
62919 
62920 		DUK_ASSERT(natfunc == duk_bi_reflect_construct);
62921 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT;
62922 		duk_remove_n_unsafe(thr, idx_func, 2);
62923 		top = duk_get_top(thr);
62924 		if (!duk_is_constructable(thr, idx_func)) {
62925 			/* Target constructability must be checked before
62926 			 * unpacking argArray (which may cause side effects).
62927 			 * Just return; caller will throw the error.
62928 			 */
62929 			duk_set_top_unsafe(thr, idx_func + 2);  /* satisfy asserts */
62930 			break;
62931 		}
62932 		duk_push_object(thr);
62933 		duk_insert(thr, idx_func + 1);  /* default instance */
62934 
62935 		/* [ ... func default_instance argArray newTarget? ] */
62936 
62937 		top = duk_get_top(thr);
62938 		if (top < idx_func + 3) {
62939 			/* argArray is a mandatory argument for Reflect.construct(). */
62940 			DUK_ERROR_TYPE_INVALID_ARGS(thr);
62941 			DUK_WO_NORETURN(return 0;);
62942 		}
62943 		if (top > idx_func + 3) {
62944 			if (!duk_strict_equals(thr, idx_func, idx_func + 3)) {
62945 				/* XXX: [[Construct]] newTarget currently unsupported */
62946 				DUK_ERROR_UNSUPPORTED(thr);
62947 				DUK_WO_NORETURN(return 0;);
62948 			}
62949 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
62950 		}
62951 		DUK_ASSERT(duk_get_top(thr) == idx_func + 3);
62952 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
62953 		(void) duk_unpack_array_like(thr, idx_func + 2);  /* XXX: should also remove target to be symmetric with duk_pack()? */
62954 		duk_remove(thr, idx_func + 2);
62955 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62956 		break;
62957 	}
62958 #endif  /* DUK_USE_REFLECT_BUILTIN */
62959 	default: {
62960 		DUK_ASSERT(0);
62961 		DUK_UNREACHABLE();
62962 	}
62963 	}
62964 
62965 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62966 	return 0;  /* keep resolving */
62967 
62968  apply_shared:
62969 	tv_args = thr->valstack_bottom + idx_func + 2;
62970 	if (thr->valstack_top <= tv_args) {
62971 		DUK_ASSERT(tv_args <= thr->valstack_end);
62972 		thr->valstack_top = tv_args;  /* at least target func and 'this' binding present */
62973 		/* No need to check for argArray. */
62974 	} else {
62975 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 3);  /* idx_func + 2 covered above */
62976 		if (thr->valstack_top > tv_args + 1) {
62977 			duk_set_top_unsafe(thr, idx_func + 3);  /* remove any args beyond argArray */
62978 		}
62979 		DUK_ASSERT(duk_is_valid_index(thr, idx_func + 2));
62980 		if (!duk_is_callable(thr, idx_func)) {
62981 			/* Avoid unpack side effects if the target isn't callable.
62982 			 * Calling code will throw the actual error.
62983 			 */
62984 		} else {
62985 			(void) duk_unpack_array_like(thr, idx_func + 2);
62986 			duk_remove(thr, idx_func + 2);
62987 		}
62988 	}
62989 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
62990 	return 0;  /* keep resolving */
62991 }
62992 
62993 /*
62994  *  Helper for Proxy handling.
62995  */
62996 
62997 #if defined(DUK_USE_ES6_PROXY)
62998 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) {
62999 	duk_bool_t rc;
63000 
63001 	/* Value stack:
63002 	 * idx_func + 0: Proxy object
63003 	 * idx_func + 1: this binding for call
63004 	 * idx_func + 2: 1st argument for call
63005 	 * idx_func + 3: 2nd argument for call
63006 	 * ...
63007 	 *
63008 	 * If Proxy doesn't have a trap for the call ('apply' or 'construct'),
63009 	 * replace Proxy object with target object.
63010 	 *
63011 	 * If we're dealing with a normal call and the Proxy has an 'apply'
63012 	 * trap, manipulate value stack to:
63013 	 *
63014 	 * idx_func + 0: trap
63015 	 * idx_func + 1: Proxy's handler
63016 	 * idx_func + 2: Proxy's target
63017 	 * idx_func + 3: this binding for call (from idx_func + 1)
63018 	 * idx_func + 4: call arguments packed to an array
63019 	 *
63020 	 * If we're dealing with a constructor call and the Proxy has a
63021 	 * 'construct' trap, manipulate value stack to:
63022 	 *
63023 	 * idx_func + 0: trap
63024 	 * idx_func + 1: Proxy's handler
63025 	 * idx_func + 2: Proxy's target
63026 	 * idx_func + 3: call arguments packed to an array
63027 	 * idx_func + 4: newTarget == Proxy object here
63028 	 *
63029 	 * As we don't yet have proper newTarget support, the newTarget at
63030 	 * idx_func + 3 is just the original constructor being called, i.e.
63031 	 * the Proxy object (not the target).  Note that the default instance
63032 	 * (original 'this' binding) is dropped and ignored.
63033 	 */
63034 
63035 	duk_push_hobject(thr, h_proxy->handler);
63036 	rc = duk_get_prop_stridx_short(thr, -1, (*call_flags & DUK_CALL_FLAG_CONSTRUCT) ? DUK_STRIDX_CONSTRUCT : DUK_STRIDX_APPLY);
63037 	if (rc == 0) {
63038 		/* Not found, continue to target.  If this is a construct
63039 		 * call, update default instance prototype using the Proxy,
63040 		 * not the target.
63041 		 */
63042 		if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63043 			if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
63044 				*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
63045 				duk__update_default_instance_proto(thr, idx_func);
63046 			}
63047 		}
63048 		duk_pop_2(thr);
63049 		duk_push_hobject(thr, h_proxy->target);
63050 		duk_replace(thr, idx_func);
63051 		return;
63052 	}
63053 
63054 	/* Here we must be careful not to replace idx_func while
63055 	 * h_proxy is still needed, otherwise h_proxy may become
63056 	 * dangling.  This could be improved e.g. using a
63057 	 * duk_pack_slice() with a freeform slice.
63058 	 */
63059 
63060 	/* Here:
63061 	 * idx_func + 0: Proxy object
63062 	 * idx_func + 1: this binding for call
63063 	 * idx_func + 2: 1st argument for call
63064 	 * idx_func + 3: 2nd argument for call
63065 	 * ...
63066 	 * idx_func + N: handler
63067 	 * idx_func + N + 1: trap
63068 	 */
63069 
63070 	duk_insert(thr, idx_func + 1);
63071 	duk_insert(thr, idx_func + 2);
63072 	duk_push_hobject(thr, h_proxy->target);
63073 	duk_insert(thr, idx_func + 3);
63074 	duk_pack(thr, duk_get_top(thr) - (idx_func + 5));
63075 
63076 	/* Here:
63077 	 * idx_func + 0: Proxy object
63078 	 * idx_func + 1: trap
63079 	 * idx_func + 2: Proxy's handler
63080 	 * idx_func + 3: Proxy's target
63081 	 * idx_func + 4: this binding for call
63082 	 * idx_func + 5: arguments array
63083 	 */
63084 	DUK_ASSERT(duk_get_top(thr) == idx_func + 6);
63085 
63086 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63087 		*call_flags |= DUK_CALL_FLAG_CONSTRUCT_PROXY;  /* Enable 'construct' trap return invariant check. */
63088 		*call_flags &= ~(DUK_CALL_FLAG_CONSTRUCT);     /* Resume as non-constructor call to the trap. */
63089 
63090 		/* 'apply' args: target, thisArg, argArray
63091 		 * 'construct' args: target, argArray, newTarget
63092 		 */
63093 		duk_remove(thr, idx_func + 4);
63094 		duk_push_hobject(thr, (duk_hobject *) h_proxy);
63095 	}
63096 
63097 	/* Finalize value stack layout by removing Proxy reference. */
63098 	duk_remove(thr, idx_func);
63099 	h_proxy = NULL;  /* invalidated */
63100 	DUK_ASSERT(duk_get_top(thr) == idx_func + 5);
63101 }
63102 #endif  /* DUK_USE_ES6_PROXY */
63103 
63104 /*
63105  *  Helper for setting up var_env and lex_env of an activation,
63106  *  assuming it does NOT have the DUK_HOBJECT_FLAG_NEWENV flag.
63107  */
63108 
63109 DUK_LOCAL void duk__handle_oldenv_for_call(duk_hthread *thr,
63110                                            duk_hobject *func,
63111                                            duk_activation *act) {
63112 	duk_hcompfunc *f;
63113 	duk_hobject *h_lex;
63114 	duk_hobject *h_var;
63115 
63116 	DUK_ASSERT(thr != NULL);
63117 	DUK_ASSERT(func != NULL);
63118 	DUK_ASSERT(act != NULL);
63119 	DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV(func));
63120 	DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
63121 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(func));
63122 	DUK_UNREF(thr);
63123 
63124 	f = (duk_hcompfunc *) func;
63125 	h_lex = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
63126 	h_var = DUK_HCOMPFUNC_GET_VARENV(thr->heap, f);
63127 	DUK_ASSERT(h_lex != NULL);  /* Always true for closures (not for templates) */
63128 	DUK_ASSERT(h_var != NULL);
63129 	act->lex_env = h_lex;
63130 	act->var_env = h_var;
63131 	DUK_HOBJECT_INCREF(thr, h_lex);
63132 	DUK_HOBJECT_INCREF(thr, h_var);
63133 }
63134 
63135 /*
63136  *  Helper for updating callee 'caller' property.
63137  */
63138 
63139 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63140 DUK_LOCAL void duk__update_func_caller_prop(duk_hthread *thr, duk_hobject *func) {
63141 	duk_tval *tv_caller;
63142 	duk_hobject *h_tmp;
63143 	duk_activation *act_callee;
63144 	duk_activation *act_caller;
63145 
63146 	DUK_ASSERT(thr != NULL);
63147 	DUK_ASSERT(func != NULL);
63148 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound chain resolved */
63149 	DUK_ASSERT(thr->callstack_top >= 1);
63150 
63151 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63152 		/* Strict functions don't get their 'caller' updated. */
63153 		return;
63154 	}
63155 
63156 	DUK_ASSERT(thr->callstack_top > 0);
63157 	act_callee = thr->callstack_curr;
63158 	DUK_ASSERT(act_callee != NULL);
63159 	act_caller = (thr->callstack_top >= 2 ? act_callee->parent : NULL);
63160 
63161 	/* XXX: check .caller writability? */
63162 
63163 	/* Backup 'caller' property and update its value. */
63164 	tv_caller = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_CALLER(thr));
63165 	if (tv_caller) {
63166 		/* If caller is global/eval code, 'caller' should be set to
63167 		 * 'null'.
63168 		 *
63169 		 * XXX: there is no exotic flag to infer this correctly now.
63170 		 * The NEWENV flag is used now which works as intended for
63171 		 * everything (global code, non-strict eval code, and functions)
63172 		 * except strict eval code.  Bound functions are never an issue
63173 		 * because 'func' has been resolved to a non-bound function.
63174 		 */
63175 
63176 		if (act_caller != NULL) {
63177 			/* act_caller->func may be NULL in some finalization cases,
63178 			 * just treat like we don't know the caller.
63179 			 */
63180 			if (act_caller->func && !DUK_HOBJECT_HAS_NEWENV(act_caller->func)) {
63181 				/* Setting to NULL causes 'caller' to be set to
63182 				 * 'null' as desired.
63183 				 */
63184 				act_caller = NULL;
63185 			}
63186 		}
63187 
63188 		if (DUK_TVAL_IS_OBJECT(tv_caller)) {
63189 			h_tmp = DUK_TVAL_GET_OBJECT(tv_caller);
63190 			DUK_ASSERT(h_tmp != NULL);
63191 			act_callee->prev_caller = h_tmp;
63192 
63193 			/* Previous value doesn't need refcount changes because its ownership
63194 			 * is transferred to prev_caller.
63195 			 */
63196 
63197 			if (act_caller != NULL) {
63198 				DUK_ASSERT(act_caller->func != NULL);
63199 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63200 				DUK_TVAL_INCREF(thr, tv_caller);
63201 			} else {
63202 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63203 			}
63204 		} else {
63205 			/* 'caller' must only take on 'null' or function value */
63206 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_caller));
63207 			DUK_ASSERT(act_callee->prev_caller == NULL);
63208 			if (act_caller != NULL && act_caller->func) {
63209 				/* Tolerate act_caller->func == NULL which happens in
63210 				 * some finalization cases; treat like unknown caller.
63211 				 */
63212 				DUK_TVAL_SET_OBJECT(tv_caller, act_caller->func);
63213 				DUK_TVAL_INCREF(thr, tv_caller);
63214 			} else {
63215 				DUK_TVAL_SET_NULL(tv_caller);  /* no incref */
63216 			}
63217 		}
63218 	}
63219 }
63220 #endif  /* DUK_USE_NONSTD_FUNC_CALLER_PROPERTY */
63221 
63222 /*
63223  *  Shared helpers for resolving the final, non-bound target function of the
63224  *  call and the effective 'this' binding.  Resolves bound functions and
63225  *  applies .call(), .apply(), and .construct() inline.
63226  *
63227  *  Proxy traps are also handled inline so that if the target is a Proxy with
63228  *  a 'call' or 'construct' trap, the trap handler is called with a modified
63229  *  argument list.
63230  *
63231  *  Once the bound function / .call() / .apply() / .construct() sequence has
63232  *  been resolved, the value at idx_func + 1 may need coercion described in
63233  *  E5 Section 10.4.3.
63234  *
63235  *  A call that begins as a non-constructor call may be converted into a
63236  *  constructor call during the resolution process if Reflect.construct()
63237  *  is invoked.  This is handled by updating the caller's call_flags.
63238  *
63239  *  For global and eval code (E5 Sections 10.4.1 and 10.4.2), we assume
63240  *  that the caller has provided the correct 'this' binding explicitly
63241  *  when calling, i.e.:
63242  *
63243  *    - global code: this=global object
63244  *    - direct eval: this=copy from eval() caller's this binding
63245  *    - other eval:  this=global object
63246  *
63247  *  The 'this' coercion may cause a recursive function call with arbitrary
63248  *  side effects, because ToObject() may be called.
63249  */
63250 
63251 DUK_LOCAL DUK_INLINE void duk__coerce_nonstrict_this_binding(duk_hthread *thr, duk_idx_t idx_this) {
63252 	duk_tval *tv_this;
63253 	duk_hobject *obj_global;
63254 
63255 	tv_this = thr->valstack_bottom + idx_this;
63256 	switch (DUK_TVAL_GET_TAG(tv_this)) {
63257 	case DUK_TAG_OBJECT:
63258 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, object -> use directly"));
63259 		break;
63260 	case DUK_TAG_UNDEFINED:
63261 	case DUK_TAG_NULL:
63262 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, undefined/null -> use global object"));
63263 		obj_global = thr->builtins[DUK_BIDX_GLOBAL];
63264 		/* XXX: avoid this check somehow */
63265 		if (DUK_LIKELY(obj_global != NULL)) {
63266 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63267 			DUK_TVAL_SET_OBJECT(tv_this, obj_global);
63268 			DUK_HOBJECT_INCREF(thr, obj_global);
63269 		} else {
63270 			/* This may only happen if built-ins are being "torn down".
63271 			 * This behavior is out of specification scope.
63272 			 */
63273 			DUK_D(DUK_DPRINT("this binding: wanted to use global object, but it is NULL -> using undefined instead"));
63274 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv_this));  /* no need to decref previous value */
63275 			DUK_TVAL_SET_UNDEFINED(tv_this);  /* nothing to incref */
63276 		}
63277 		break;
63278 	default:
63279 		/* Plain buffers and lightfuncs are object coerced.  Lightfuncs
63280 		 * very rarely come here however, because the call target would
63281 		 * need to be a non-strict non-lightfunc (lightfuncs are considered
63282 		 * strict) with an explicit lightfunc 'this' binding.
63283 		 */
63284 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_this));
63285 		DUK_DDD(DUK_DDDPRINT("this binding: non-strict, not object/undefined/null -> use ToObject(value)"));
63286 		duk_to_object(thr, idx_this);  /* may have side effects */
63287 		break;
63288 	}
63289 }
63290 
63291 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) {
63292 #if defined(DUK_USE_PREFER_SIZE)
63293 	DUK_UNREF(thr);
63294 	DUK_UNREF(idx_func);
63295 	DUK_UNREF(out_func);
63296 	DUK_UNREF(call_flags);
63297 #else  /* DUK_USE_PREFER_SIZE */
63298 	duk_tval *tv_func;
63299 	duk_hobject *func;
63300 
63301 	if (DUK_UNLIKELY(call_flags & DUK_CALL_FLAG_CONSTRUCT)) {
63302 		return 0;
63303 	}
63304 
63305 	tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63306 	DUK_ASSERT(tv_func != NULL);
63307 
63308 	if (DUK_LIKELY(DUK_TVAL_IS_OBJECT(tv_func))) {
63309 		func = DUK_TVAL_GET_OBJECT(tv_func);
63310 		if (DUK_HOBJECT_IS_CALLABLE(func) &&
63311 		    !DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63312 		    !DUK_HOBJECT_HAS_SPECIAL_CALL(func)) {
63313 			*out_func = func;
63314 
63315 			if (DUK_HOBJECT_HAS_STRICT(func)) {
63316 				/* Strict function: no 'this' coercion. */
63317 				return 1;
63318 			}
63319 
63320 			duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
63321 			return 1;
63322 		}
63323 	} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63324 		*out_func = NULL;
63325 
63326 		/* Lightfuncs are considered strict, so 'this' binding is
63327 		 * used as is.  They're never bound, always constructable,
63328 		 * and never special functions.
63329 		 */
63330 		return 1;
63331 	}
63332 #endif  /* DUK_USE_PREFER_SIZE */
63333 	return 0;  /* let slow path deal with it */
63334 }
63335 
63336 DUK_LOCAL duk_hobject *duk__resolve_target_func_and_this_binding(duk_hthread *thr,
63337                                                                  duk_idx_t idx_func,
63338                                                                  duk_small_uint_t *call_flags) {
63339 	duk_tval *tv_func;
63340 	duk_hobject *func;
63341 	duk_bool_t first;
63342 
63343 	DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63344 
63345 	for (first = 1;; first = 0) {
63346 		DUK_ASSERT(duk_get_top(thr) >= idx_func + 2);
63347 
63348 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63349 		DUK_ASSERT(tv_func != NULL);
63350 
63351 		if (DUK_TVAL_IS_OBJECT(tv_func)) {
63352 			func = DUK_TVAL_GET_OBJECT(tv_func);
63353 
63354 			if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63355 				if (DUK_UNLIKELY(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func))) {
63356 					goto not_constructable;
63357 				}
63358 			} else {
63359 				if (DUK_UNLIKELY(!DUK_HOBJECT_IS_CALLABLE(func))) {
63360 					goto not_callable;
63361 				}
63362 			}
63363 
63364 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_BOUNDFUNC(func) &&
63365 			               !DUK_HOBJECT_HAS_SPECIAL_CALL(func) &&
63366 			               !DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func))) {
63367 				/* Common case, so test for using a single bitfield test.
63368 				 * Break out to handle this coercion etc.
63369 				 */
63370 				break;
63371 			}
63372 
63373 			/* XXX: could set specialcall for boundfuncs too, simplify check above */
63374 
63375 			if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
63376 				DUK_ASSERT(!DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63377 				DUK_ASSERT(!DUK_HOBJECT_IS_NATFUNC(func));
63378 
63379 				/* Callable/constructable flags are the same
63380 				 * for the bound function and its target, so
63381 				 * we don't need to check them here, we can
63382 				 * check them from the target only.
63383 				 */
63384 				duk__handle_bound_chain_for_call(thr, idx_func, *call_flags & DUK_CALL_FLAG_CONSTRUCT);
63385 
63386 				DUK_ASSERT(DUK_TVAL_IS_OBJECT(duk_require_tval(thr, idx_func)) ||
63387 				           DUK_TVAL_IS_LIGHTFUNC(duk_require_tval(thr, idx_func)));
63388 			} else {
63389 				DUK_ASSERT(DUK_HOBJECT_HAS_SPECIAL_CALL(func));
63390 
63391 #if defined(DUK_USE_ES6_PROXY)
63392 				if (DUK_HOBJECT_HAS_EXOTIC_PROXYOBJ(func)) {
63393 					/* If no trap, resume processing from Proxy trap.
63394 					 * If trap exists, helper converts call into a trap
63395 					 * call; this may change a constructor call into a
63396 					 * normal (non-constructor) trap call.  We must
63397 					 * continue processing even when a trap is found as
63398 					 * the trap may be bound.
63399 					 */
63400 					duk__handle_proxy_for_call(thr, idx_func, (duk_hproxy *) func, call_flags);
63401 				}
63402 				else
63403 #endif
63404 				{
63405 					DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
63406 					DUK_ASSERT(DUK_HOBJECT_HAS_CALLABLE(func));
63407 					DUK_ASSERT(!DUK_HOBJECT_HAS_CONSTRUCTABLE(func));
63408 					/* Constructable check already done above. */
63409 
63410 					if (duk__handle_specialfuncs_for_call(thr, idx_func, func, call_flags, first) != 0) {
63411 						/* Encountered native eval call, normal call
63412 						 * context.  Break out, handle this coercion etc.
63413 						 */
63414 						break;
63415 					}
63416 				}
63417 			}
63418 			/* Retry loop. */
63419 		} else if (DUK_TVAL_IS_LIGHTFUNC(tv_func)) {
63420 			/* Lightfuncs are:
63421 			 *   - Always strict, so no 'this' coercion.
63422 			 *   - Always callable.
63423 			 *   - Always constructable.
63424 			 *   - Never specialfuncs.
63425 			 */
63426 			func = NULL;
63427 			goto finished;
63428 		} else {
63429 			goto not_callable;
63430 		}
63431 	}
63432 
63433 	DUK_ASSERT(func != NULL);
63434 
63435 	if (!DUK_HOBJECT_HAS_STRICT(func)) {
63436 		/* Non-strict target needs 'this' coercion.
63437 		 * This has potential side effects invalidating
63438 		 * 'tv_func'.
63439 		 */
63440 		duk__coerce_nonstrict_this_binding(thr, idx_func + 1);
63441 	}
63442 	if (*call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63443 		if (!(*call_flags & DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED)) {
63444 			*call_flags |= DUK_CALL_FLAG_DEFAULT_INSTANCE_UPDATED;
63445 			duk__update_default_instance_proto(thr, idx_func);
63446 		}
63447 	}
63448 
63449  finished:
63450 
63451 #if defined(DUK_USE_ASSERTIONS)
63452 	{
63453 		duk_tval *tv_tmp;
63454 
63455 		tv_tmp = duk_get_tval(thr, idx_func);
63456 		DUK_ASSERT(tv_tmp != NULL);
63457 
63458 		DUK_ASSERT((DUK_TVAL_IS_OBJECT(tv_tmp) && DUK_HOBJECT_IS_CALLABLE(DUK_TVAL_GET_OBJECT(tv_tmp))) ||
63459 		           DUK_TVAL_IS_LIGHTFUNC(tv_tmp));
63460 		DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
63461 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
63462 		                            DUK_HOBJECT_IS_NATFUNC(func)));
63463 		DUK_ASSERT(func == NULL || (DUK_HOBJECT_HAS_CONSTRUCTABLE(func) ||
63464 		                            (*call_flags & DUK_CALL_FLAG_CONSTRUCT) == 0));
63465 	}
63466 #endif
63467 
63468 	return func;
63469 
63470  not_callable:
63471 	DUK_ASSERT(tv_func != NULL);
63472 
63473 #if defined(DUK_USE_VERBOSE_ERRORS)
63474 	/* GETPROPC delayed error handling: when target is not callable,
63475 	 * GETPROPC replaces idx_func+0 with an Error (non-callable) with
63476 	 * a hidden Symbol to signify it's to be thrown as is here.  The
63477 	 * hidden Symbol is only checked as an own property, not inherited
63478 	 * (which would be dangerous).
63479 	 */
63480 	if (DUK_TVAL_IS_OBJECT(tv_func)) {
63481 		if (duk_hobject_find_existing_entry_tval_ptr(thr->heap, DUK_TVAL_GET_OBJECT(tv_func), DUK_HTHREAD_STRING_INT_TARGET(thr)) != NULL) {
63482 			duk_push_tval(thr, tv_func);
63483 			(void) duk_throw(thr);
63484 			DUK_WO_NORETURN(return NULL;);
63485 		}
63486 	}
63487 #endif
63488 
63489 #if defined(DUK_USE_VERBOSE_ERRORS)
63490 #if defined(DUK_USE_PARANOID_ERRORS)
63491 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_get_type_name(thr, idx_func));
63492 #else
63493 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not callable", duk_push_string_tval_readable(thr, tv_func));
63494 #endif
63495 #else
63496 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CALLABLE);
63497 #endif
63498 	DUK_WO_NORETURN(return NULL;);
63499 
63500  not_constructable:
63501 	/* For now GETPROPC delayed error not needed for constructor calls. */
63502 #if defined(DUK_USE_VERBOSE_ERRORS)
63503 #if defined(DUK_USE_PARANOID_ERRORS)
63504 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_get_type_name(thr, idx_func));
63505 #else
63506 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "%s not constructable", duk_push_string_tval_readable(thr, tv_func));
63507 #endif
63508 #else
63509 	DUK_ERROR_TYPE(thr, DUK_STR_NOT_CONSTRUCTABLE);
63510 #endif
63511 	DUK_WO_NORETURN(return NULL;);
63512 }
63513 
63514 /*
63515  *  Manipulate value stack so that exactly 'num_stack_rets' return
63516  *  values are at 'idx_retbase' in every case, assuming there are
63517  *  'rc' return values on top of stack.
63518  *
63519  *  This is a bit tricky, because the called C function operates in
63520  *  the same activation record and may have e.g. popped the stack
63521  *  empty (below idx_retbase).
63522  */
63523 
63524 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) {
63525 	duk_idx_t idx_rcbase;
63526 
63527 	DUK_ASSERT(thr != NULL);
63528 	DUK_ASSERT(idx_retbase >= 0);
63529 	DUK_ASSERT(num_stack_rets >= 0);
63530 	DUK_ASSERT(num_actual_rets >= 0);
63531 
63532 	idx_rcbase = duk_get_top(thr) - num_actual_rets;  /* base of known return values */
63533 	if (DUK_UNLIKELY(idx_rcbase < 0)) {
63534 		DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
63535 		DUK_WO_NORETURN(return;);
63536 	}
63537 
63538 	DUK_DDD(DUK_DDDPRINT("adjust valstack after func call: "
63539 	                     "num_stack_rets=%ld, num_actual_rets=%ld, stack_top=%ld, idx_retbase=%ld, idx_rcbase=%ld",
63540 	                     (long) num_stack_rets, (long) num_actual_rets, (long) duk_get_top(thr),
63541 	                     (long) idx_retbase, (long) idx_rcbase));
63542 
63543 	DUK_ASSERT(idx_rcbase >= 0);  /* caller must check */
63544 
63545 	/* Space for num_stack_rets was reserved before the safe call.
63546 	 * Because value stack reserve cannot shrink except in call returns,
63547 	 * the reserve is still in place.  Adjust valstack, carefully
63548 	 * ensuring we don't overstep the reserve.
63549 	 */
63550 
63551 	/* Match idx_rcbase with idx_retbase so that the return values
63552 	 * start at the correct index.
63553 	 */
63554 	if (idx_rcbase > idx_retbase) {
63555 		duk_idx_t count = idx_rcbase - idx_retbase;
63556 
63557 		DUK_DDD(DUK_DDDPRINT("elements at/after idx_retbase have enough to cover func retvals "
63558 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
63559 
63560 		/* Remove values between irc_rcbase (start of intended return
63561 		 * values) and idx_retbase to lower return values to idx_retbase.
63562 		 */
63563 		DUK_ASSERT(count > 0);
63564 		duk_remove_n(thr, idx_retbase, count);  /* may be NORZ */
63565 	} else {
63566 		duk_idx_t count = idx_retbase - idx_rcbase;
63567 
63568 		DUK_DDD(DUK_DDDPRINT("not enough elements at/after idx_retbase to cover func retvals "
63569 		                     "(idx_retbase=%ld, idx_rcbase=%ld)", (long) idx_retbase, (long) idx_rcbase));
63570 
63571 		/* Insert 'undefined' at idx_rcbase (start of intended return
63572 		 * values) to lift return values to idx_retbase.
63573 		 */
63574 		DUK_ASSERT(count >= 0);
63575 		DUK_ASSERT(thr->valstack_end - thr->valstack_top >= count);  /* reserve cannot shrink */
63576 		duk_insert_undefined_n(thr, idx_rcbase, count);
63577 	}
63578 
63579 	/* Chop extra retvals away / extend with undefined. */
63580 	duk_set_top_unsafe(thr, idx_retbase + num_stack_rets);
63581 }
63582 
63583 /*
63584  *  Activation setup for tailcalls and non-tailcalls.
63585  */
63586 
63587 #if defined(DUK_USE_TAILCALL)
63588 DUK_LOCAL duk_small_uint_t duk__call_setup_act_attempt_tailcall(duk_hthread *thr,
63589                                                                 duk_small_uint_t call_flags,
63590                                                                 duk_idx_t idx_func,
63591                                                                 duk_hobject *func,
63592                                                                 duk_size_t entry_valstack_bottom_byteoff,
63593                                                                 duk_size_t entry_valstack_end_byteoff,
63594                                                                 duk_idx_t *out_nargs,
63595                                                                 duk_idx_t *out_nregs,
63596                                                                 duk_size_t *out_vs_min_bytes,
63597                                                                 duk_activation **out_act) {
63598 	duk_activation *act;
63599 	duk_tval *tv1, *tv2;
63600 	duk_idx_t idx_args;
63601 	duk_small_uint_t flags1, flags2;
63602 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63603 	duk_activation *prev_pause_act;
63604 #endif
63605 
63606 	DUK_UNREF(entry_valstack_end_byteoff);
63607 
63608 	/* Tailcall cannot be flagged to resume calls, and a
63609 	 * previous frame must exist.
63610 	 */
63611 	DUK_ASSERT(thr->callstack_top >= 1);
63612 
63613 	act = thr->callstack_curr;
63614 	DUK_ASSERT(act != NULL);
63615 	*out_act = act;
63616 
63617 	if (func == NULL || !DUK_HOBJECT_IS_COMPFUNC(func)) {
63618 		DUK_DDD(DUK_DDDPRINT("tail call prevented by target not being ecma function"));
63619 		return 0;
63620 	}
63621 	if (act->flags & DUK_ACT_FLAG_PREVENT_YIELD) {
63622 		DUK_DDD(DUK_DDDPRINT("tail call prevented by current activation having DUK_ACT_FLAG_PREVENT_YIELD"));
63623 		return 0;
63624 	}
63625 	/* Tailcall is only allowed if current and candidate
63626 	 * function have identical return value handling.  There
63627 	 * are three possible return value handling cases:
63628 	 *   1. Normal function call, no special return value handling.
63629 	 *   2. Constructor call, return value replacement object check.
63630 	 *   3. Proxy 'construct' trap call, return value invariant check.
63631 	 */
63632 	flags1 = (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT) ? 1 : 0)
63633 #if defined(DUK_USE_ES6_PROXY)
63634 	         | (duk_small_uint_t) ((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) ? 2 : 0)
63635 #endif
63636 	         ;
63637 	flags2 = (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) ? 1 : 0)
63638 #if defined(DUK_USE_ES6_PROXY)
63639 	         | (duk_small_uint_t) ((call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) ? 2 : 0);
63640 #endif
63641 	         ;
63642 	if (flags1 != flags2) {
63643 		DUK_DDD(DUK_DDDPRINT("tail call prevented by incompatible return value handling"));
63644 		return 0;
63645 	}
63646 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT) && (call_flags & DUK_CALL_FLAG_CONSTRUCT)) ||
63647 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT)));
63648 	DUK_ASSERT(((act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)) ||
63649 	           (!(act->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY) && !(call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY)));
63650 	if (DUK_HOBJECT_HAS_NOTAIL(func)) {
63651 		/* See: test-bug-tailcall-preventyield-assert.c. */
63652 		DUK_DDD(DUK_DDDPRINT("tail call prevented by function having a notail flag"));
63653 		return 0;
63654 	}
63655 
63656 	/*
63657 	 *  Tailcall handling
63658 	 *
63659 	 *  Although the callstack entry is reused, we need to explicitly unwind
63660 	 *  the current activation (or simulate an unwind).  In particular, the
63661 	 *  current activation must be closed, otherwise something like
63662 	 *  test-bug-reduce-judofyr.js results.  Also catchers need to be unwound
63663 	 *  because there may be non-error-catching label entries in valid tail calls.
63664 	 *
63665 	 *  Special attention is needed for debugger and pause behavior when
63666 	 *  reusing an activation.
63667 	 *    - Disable StepOut processing for the activation unwind because
63668 	 *      we reuse the activation, see:
63669 	 *      https://github.com/svaarala/duktape/issues/1684.
63670 	 *    - Disable line change pause flag permanently if act == dbg_pause_act
63671 	 *      (if set) because it would no longer be relevant, see:
63672 	 *      https://github.com/svaarala/duktape/issues/1726,
63673 	 *      https://github.com/svaarala/duktape/issues/1786.
63674 	 *    - Check for function entry (e.g. StepInto) pause flag here, because
63675 	 *      the executor pause check won't trigger due to shared activation, see:
63676 	 *      https://github.com/svaarala/duktape/issues/1726.
63677 	 */
63678 
63679 	DUK_DDD(DUK_DDDPRINT("is tail call, reusing activation at callstack top, at index %ld",
63680                              (long) (thr->callstack_top - 1)));
63681 
63682 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
63683 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(func));
63684 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
63685 	DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
63686 	DUK_ASSERT(call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA);
63687 
63688 	/* Unwind the topmost callstack entry before reusing it.  This
63689 	 * also unwinds the catchers related to the topmost entry.
63690 	 */
63691 	DUK_ASSERT(thr->callstack_top > 0);
63692 	DUK_ASSERT(thr->callstack_curr != NULL);
63693 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63694 	if (act == thr->heap->dbg_pause_act) {
63695 		thr->heap->dbg_pause_flags &= ~DUK_PAUSE_FLAG_LINE_CHANGE;
63696 	}
63697 
63698 	prev_pause_act = thr->heap->dbg_pause_act;
63699 	thr->heap->dbg_pause_act = NULL;
63700 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) {
63701 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry (tailcall)"));
63702 		duk_debug_set_paused(thr->heap);
63703 	}
63704 #endif
63705 	duk_hthread_activation_unwind_reuse_norz(thr);
63706 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63707 	thr->heap->dbg_pause_act = prev_pause_act;
63708 #endif
63709 	DUK_ASSERT(act == thr->callstack_curr);
63710 
63711 	/* XXX: We could restore the caller's value stack reserve
63712 	 * here, as if we did an actual unwind-and-call.  Without
63713 	 * the restoration, value stack reserve may remain higher
63714 	 * than would otherwise be possible until we return to a
63715 	 * non-tailcall.
63716 	 */
63717 
63718 	/* Then reuse the unwound activation. */
63719 	act->cat = NULL;
63720 	act->var_env = NULL;
63721 	act->lex_env = NULL;
63722 	DUK_ASSERT(func != NULL);
63723 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
63724 	act->func = func;  /* don't want an intermediate exposed state with func == NULL */
63725 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63726 	act->prev_caller = NULL;
63727 #endif
63728 	/* don't want an intermediate exposed state with invalid pc */
63729 	act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
63730 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63731 	act->prev_line = 0;
63732 #endif
63733 	DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
63734 	DUK_HOBJECT_INCREF(thr, func);
63735 
63736 	act->flags = DUK_ACT_FLAG_TAILCALLED;
63737 	if (DUK_HOBJECT_HAS_STRICT(func)) {
63738 		act->flags |= DUK_ACT_FLAG_STRICT;
63739 	}
63740 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63741 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
63742 	}
63743 #if defined(DUK_USE_ES6_PROXY)
63744 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
63745 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
63746 	}
63747 #endif
63748 
63749 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) == func);      /* already updated */
63750 	DUK_ASSERT(act->var_env == NULL);
63751 	DUK_ASSERT(act->lex_env == NULL);
63752 	act->bottom_byteoff = entry_valstack_bottom_byteoff;  /* tail call -> reuse current "frame" */
63753 #if 0
63754 	/* Topmost activation retval_byteoff is considered garbage, no need to init. */
63755 	act->retval_byteoff = 0;
63756 #endif
63757 	/* Filled in when final reserve is known, dummy value doesn't matter
63758 	 * even in error unwind because reserve_byteoff is only used when
63759 	 * returning to -this- activation.
63760 	 */
63761 	act->reserve_byteoff = 0;
63762 
63763 	/*
63764 	 *  Manipulate valstack so that args are on the current bottom and the
63765 	 *  previous caller's 'this' binding (which is the value preceding the
63766 	 *  current bottom) is replaced with the new 'this' binding:
63767 	 *
63768 	 *       [ ... this_old | (crud) func this_new arg1 ... argN ]
63769 	 *  -->  [ ... this_new | arg1 ... argN ]
63770 	 *
63771 	 *  For tail calling to work properly, the valstack bottom must not grow
63772 	 *  here; otherwise crud would accumulate on the valstack.
63773 	 */
63774 
63775 	tv1 = thr->valstack_bottom - 1;
63776 	tv2 = thr->valstack_bottom + idx_func + 1;
63777 	DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);  /* tv1 is -below- valstack_bottom */
63778 	DUK_ASSERT(tv2 >= thr->valstack_bottom && tv2 < thr->valstack_top);
63779 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
63780 
63781 	idx_args = idx_func + 2;
63782 	duk_remove_n(thr, 0, idx_args);  /* may be NORZ */
63783 
63784 	idx_func = 0; DUK_UNREF(idx_func);  /* really 'not applicable' anymore, should not be referenced after this */
63785 	idx_args = 0;
63786 
63787 	*out_nargs = ((duk_hcompfunc *) func)->nargs;
63788 	*out_nregs = ((duk_hcompfunc *) func)->nregs;
63789 	DUK_ASSERT(*out_nregs >= 0);
63790 	DUK_ASSERT(*out_nregs >= *out_nargs);
63791 	*out_vs_min_bytes = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
63792 
63793 
63794 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63795 #if defined(DUK_USE_TAILCALL)
63796 #error incorrect options: tail calls enabled with function caller property
63797 #endif
63798 	/* XXX: This doesn't actually work properly for tail calls, so
63799 	 * tail calls are disabled when DUK_USE_NONSTD_FUNC_CALLER_PROPERTY
63800 	 * is in use.
63801 	 */
63802 	duk__update_func_caller_prop(thr, func);
63803 #endif
63804 
63805 	/* [ ... this_new | arg1 ... argN ] */
63806 
63807 	return 1;
63808 }
63809 #endif  /* DUK_USE_TAILCALL */
63810 
63811 DUK_LOCAL void duk__call_setup_act_not_tailcall(duk_hthread *thr,
63812                                                 duk_small_uint_t call_flags,
63813                                                 duk_idx_t idx_func,
63814                                                 duk_hobject *func,
63815                                                 duk_size_t entry_valstack_bottom_byteoff,
63816                                                 duk_size_t entry_valstack_end_byteoff,
63817                                                 duk_idx_t *out_nargs,
63818                                                 duk_idx_t *out_nregs,
63819                                                 duk_size_t *out_vs_min_bytes,
63820                                                 duk_activation **out_act) {
63821 	duk_activation *act;
63822 	duk_activation *new_act;
63823 
63824 	DUK_UNREF(entry_valstack_end_byteoff);
63825 
63826 	DUK_DDD(DUK_DDDPRINT("not a tail call, pushing a new activation to callstack, to index %ld",
63827 	                     (long) (thr->callstack_top)));
63828 
63829 	duk__call_callstack_limit_check(thr);
63830 	new_act = duk_hthread_activation_alloc(thr);
63831 	DUK_ASSERT(new_act != NULL);
63832 
63833 	act = thr->callstack_curr;
63834 	if (act != NULL) {
63835 		/*
63836 		 *  Update return value stack index of current activation (if any).
63837 		 *
63838 		 *  Although it might seem this is not necessary (bytecode executor
63839 		 *  does this for ECMAScript-to-ECMAScript calls; other calls are
63840 		 *  handled here), this turns out to be necessary for handling yield
63841 		 *  and resume.  For them, an ECMAScript-to-native call happens, and
63842 		 *  the ECMAScript call's retval_byteoff must be set for things to work.
63843 		 */
63844 
63845 		act->retval_byteoff = entry_valstack_bottom_byteoff + (duk_size_t) idx_func * sizeof(duk_tval);
63846 	}
63847 
63848 	new_act->parent = act;
63849 	thr->callstack_curr = new_act;
63850 	thr->callstack_top++;
63851 	act = new_act;
63852 	*out_act = act;
63853 
63854 	DUK_ASSERT(thr->valstack_top > thr->valstack_bottom);  /* at least effective 'this' */
63855 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
63856 
63857 	act->cat = NULL;
63858 
63859 	act->flags = 0;
63860 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
63861 		act->flags |= DUK_ACT_FLAG_CONSTRUCT;
63862 	}
63863 #if defined(DUK_USE_ES6_PROXY)
63864 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY) {
63865 		act->flags |= DUK_ACT_FLAG_CONSTRUCT_PROXY;
63866 	}
63867 #endif
63868 	if (call_flags & DUK_CALL_FLAG_DIRECT_EVAL) {
63869 		act->flags |= DUK_ACT_FLAG_DIRECT_EVAL;
63870 	}
63871 
63872 	/* start of arguments: idx_func + 2. */
63873 	act->func = func;  /* NULL for lightfunc */
63874 	if (DUK_LIKELY(func != NULL)) {
63875 		DUK_TVAL_SET_OBJECT(&act->tv_func, func);  /* borrowed, no refcount */
63876 		if (DUK_HOBJECT_HAS_STRICT(func)) {
63877 			act->flags |= DUK_ACT_FLAG_STRICT;
63878 		}
63879 		if (DUK_HOBJECT_IS_COMPFUNC(func)) {
63880 			*out_nargs = ((duk_hcompfunc *) func)->nargs;
63881 			*out_nregs = ((duk_hcompfunc *) func)->nregs;
63882 			DUK_ASSERT(*out_nregs >= 0);
63883 			DUK_ASSERT(*out_nregs >= *out_nargs);
63884 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63885 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_INTERNAL_EXTRA);
63886 		} else {
63887 			/* True because of call target lookup checks. */
63888 			DUK_ASSERT(DUK_HOBJECT_IS_NATFUNC(func));
63889 
63890 			*out_nargs = ((duk_hnatfunc *) func)->nargs;
63891 			*out_nregs = *out_nargs;
63892 			if (*out_nargs >= 0) {
63893 				*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63894 					sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nregs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63895 			} else {
63896 				/* Vararg function. */
63897 				duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
63898 				*out_vs_min_bytes = valstack_top_byteoff +
63899 					sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63900 			}
63901 		}
63902 	} else {
63903 		duk_small_uint_t lf_flags;
63904 		duk_tval *tv_func;
63905 
63906 		act->flags |= DUK_ACT_FLAG_STRICT;
63907 
63908 		tv_func = DUK_GET_TVAL_POSIDX(thr, idx_func);
63909 		DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
63910 		DUK_TVAL_SET_TVAL(&act->tv_func, tv_func);  /* borrowed, no refcount */
63911 
63912 		lf_flags = DUK_TVAL_GET_LIGHTFUNC_FLAGS(tv_func);
63913 		*out_nargs = DUK_LFUNC_FLAGS_GET_NARGS(lf_flags);
63914 		if (*out_nargs != DUK_LFUNC_NARGS_VARARGS) {
63915 			*out_vs_min_bytes = entry_valstack_bottom_byteoff +
63916 				sizeof(duk_tval) * ((duk_size_t) idx_func + 2U + (duk_size_t) *out_nargs + DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63917 		} else {
63918 			duk_size_t valstack_top_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_top - ((duk_uint8_t *) thr->valstack));
63919 			*out_vs_min_bytes = valstack_top_byteoff +
63920 				sizeof(duk_tval) * (DUK_VALSTACK_API_ENTRY_MINIMUM + DUK_VALSTACK_INTERNAL_EXTRA);
63921 			*out_nargs = -1;  /* vararg */
63922 		}
63923 		*out_nregs = *out_nargs;
63924 	}
63925 
63926 	act->var_env = NULL;
63927 	act->lex_env = NULL;
63928 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63929 	act->prev_caller = NULL;
63930 #endif
63931 	act->curr_pc = NULL;
63932 #if defined(DUK_USE_DEBUGGER_SUPPORT)
63933 	act->prev_line = 0;
63934 #endif
63935 	act->bottom_byteoff = entry_valstack_bottom_byteoff + sizeof(duk_tval) * ((duk_size_t) idx_func + 2U);
63936 #if 0
63937 	act->retval_byteoff = 0;   /* topmost activation retval_byteoff is considered garbage, no need to init */
63938 #endif
63939 	/* Filled in when final reserve is known, dummy value doesn't matter
63940 	 * even in error unwind because reserve_byteoff is only used when
63941 	 * returning to -this- activation.
63942 	 */
63943 	act->reserve_byteoff = 0;  /* filled in by caller */
63944 
63945 	/* XXX: Is this INCREF necessary? 'func' is always a borrowed
63946 	 * reference reachable through the value stack?  If changed, stack
63947 	 * unwind code also needs to be fixed to match.
63948 	 */
63949 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, func);  /* act->func */
63950 
63951 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
63952 	if (func) {
63953 		duk__update_func_caller_prop(thr, func);
63954 	}
63955 #endif
63956 }
63957 
63958 /*
63959  *  Environment setup.
63960  */
63961 
63962 DUK_LOCAL void duk__call_env_setup(duk_hthread *thr, duk_hobject *func, duk_activation *act, duk_idx_t idx_args) {
63963 	duk_hobject *env;
63964 
63965 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound function has already been resolved */
63966 
63967 	if (DUK_LIKELY(func != NULL)) {
63968 		if (DUK_LIKELY(DUK_HOBJECT_HAS_NEWENV(func))) {
63969 			if (DUK_LIKELY(!DUK_HOBJECT_HAS_CREATEARGS(func))) {
63970 				/* Use a new environment but there's no 'arguments' object;
63971 				 * delayed environment initialization.  This is the most
63972 				 * common case.
63973 				 */
63974 				DUK_ASSERT(act->lex_env == NULL);
63975 				DUK_ASSERT(act->var_env == NULL);
63976 			} else {
63977 				/* Use a new environment and there's an 'arguments' object.
63978 				 * We need to initialize it right now.
63979 				 */
63980 
63981 				/* third arg: absolute index (to entire valstack) of bottom_byteoff of new activation */
63982 				env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
63983 				DUK_ASSERT(env != NULL);
63984 
63985 				/* [ ... func this arg1 ... argN envobj ] */
63986 
63987 				DUK_ASSERT(DUK_HOBJECT_HAS_CREATEARGS(func));
63988 				duk__handle_createargs_for_call(thr, func, env, idx_args);
63989 
63990 				/* [ ... func this arg1 ... argN envobj ] */
63991 
63992 				act->lex_env = env;
63993 				act->var_env = env;
63994 				DUK_HOBJECT_INCREF(thr, env);
63995 				DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (2) directly */
63996 				duk_pop(thr);
63997 			}
63998 		} else {
63999 			/* Use existing env (e.g. for non-strict eval); cannot have
64000 			 * an own 'arguments' object (but can refer to an existing one).
64001 			 */
64002 
64003 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
64004 
64005 			duk__handle_oldenv_for_call(thr, func, act);
64006 
64007 			DUK_ASSERT(act->lex_env != NULL);
64008 			DUK_ASSERT(act->var_env != NULL);
64009 		}
64010 	} else {
64011 		/* Lightfuncs are always native functions and have "newenv". */
64012 		DUK_ASSERT(act->lex_env == NULL);
64013 		DUK_ASSERT(act->var_env == NULL);
64014 	}
64015 }
64016 
64017 /*
64018  *  Misc shared helpers.
64019  */
64020 
64021 /* Check thread state, update current thread. */
64022 DUK_LOCAL void duk__call_thread_state_update(duk_hthread *thr) {
64023 	DUK_ASSERT(thr != NULL);
64024 
64025 	if (DUK_LIKELY(thr == thr->heap->curr_thread)) {
64026 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_RUNNING)) {
64027 			/* Should actually never happen, but check anyway. */
64028 			goto thread_state_error;
64029 		}
64030 	} else {
64031 		DUK_ASSERT(thr->heap->curr_thread == NULL ||
64032 		           thr->heap->curr_thread->state == DUK_HTHREAD_STATE_RUNNING);
64033 		if (DUK_UNLIKELY(thr->state != DUK_HTHREAD_STATE_INACTIVE)) {
64034 			goto thread_state_error;
64035 		}
64036 		DUK_HEAP_SWITCH_THREAD(thr->heap, thr);
64037 		thr->state = DUK_HTHREAD_STATE_RUNNING;
64038 
64039 		/* Multiple threads may be simultaneously in the RUNNING
64040 		 * state, but not in the same "resume chain".
64041 		 */
64042 	}
64043 	DUK_ASSERT(thr->heap->curr_thread == thr);
64044 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
64045 	return;
64046 
64047  thread_state_error:
64048 	DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "invalid thread state (%ld)", (long) thr->state);
64049 	DUK_WO_NORETURN(return;);
64050 }
64051 
64052 /*
64053  *  Main unprotected call handler, handles:
64054  *
64055  *    - All combinations of native/ECMAScript caller and native/ECMAScript
64056  *      target.
64057  *
64058  *    - Optimized ECMAScript-to-ECMAScript call where call handling only
64059  *      sets up a new duk_activation but reuses an existing bytecode executor
64060  *      (the caller) without native recursion.
64061  *
64062  *    - Tailcalls, where an activation is reused without increasing call
64063  *      stack (duk_activation) depth.
64064  *
64065  *    - Setup for an initial Duktape.Thread.resume().
64066  *
64067  *  The call handler doesn't provide any protection guarantees, protected calls
64068  *  must be implemented e.g. by wrapping the call in a duk_safe_call().
64069  *  Call setup may fail at any stage, even when the new activation is in
64070  *  place; the only guarantee is that the state is consistent for unwinding.
64071  */
64072 
64073 DUK_LOCAL duk_int_t duk__handle_call_raw(duk_hthread *thr,
64074                                          duk_idx_t idx_func,
64075                                          duk_small_uint_t call_flags) {
64076 #if defined(DUK_USE_ASSERTIONS)
64077 	duk_activation *entry_act;
64078 	duk_size_t entry_callstack_top;
64079 #endif
64080 	duk_size_t entry_valstack_bottom_byteoff;
64081 	duk_size_t entry_valstack_end_byteoff;
64082 	duk_int_t entry_call_recursion_depth;
64083 	duk_hthread *entry_curr_thread;
64084 	duk_uint_fast8_t entry_thread_state;
64085 	duk_instr_t **entry_ptr_curr_pc;
64086 	duk_idx_t idx_args;
64087 	duk_idx_t nargs;            /* # argument registers target function wants (< 0 => "as is") */
64088 	duk_idx_t nregs;            /* # total registers target function wants on entry (< 0 => "as is") */
64089 	duk_size_t vs_min_bytes;    /* minimum value stack size (bytes) for handling call */
64090 	duk_hobject *func;          /* 'func' on stack (borrowed reference) */
64091 	duk_activation *act;
64092 	duk_ret_t rc;
64093 	duk_small_uint_t use_tailcall;
64094 
64095 	DUK_ASSERT(thr != NULL);
64096 	DUK_ASSERT(thr->heap != NULL);
64097 	/* Asserts for heap->curr_thread omitted: it may be NULL, 'thr', or
64098 	 * any other thread (e.g. when heap thread is used to run finalizers).
64099 	 */
64100 	DUK_ASSERT_CTX_VALID(thr);
64101 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
64102 	DUK_ASSERT(idx_func >= 0);
64103 
64104 	DUK_STATS_INC(thr->heap, stats_call_all);
64105 
64106 	/* If a tail call:
64107 	 *   - an ECMAScript activation must be on top of the callstack
64108 	 *   - there cannot be any catch stack entries that would catch
64109 	 *     a return
64110 	 */
64111 #if defined(DUK_USE_ASSERTIONS)
64112 	if (call_flags & DUK_CALL_FLAG_TAILCALL) {
64113 		duk_activation *tmp_act;
64114 		duk_catcher *tmp_cat;
64115 
64116 		DUK_ASSERT(thr->callstack_top >= 1);
64117 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
64118 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
64119 
64120 		/* No entry in the catch stack which would actually catch a
64121 		 * throw can refer to the callstack entry being reused.
64122 		 * There *can* be catch stack entries referring to the current
64123 		 * callstack entry as long as they don't catch (e.g. label sites).
64124 		 */
64125 
64126 		tmp_act = thr->callstack_curr;
64127 		for (tmp_cat = tmp_act->cat; tmp_cat != NULL; tmp_cat = tmp_cat->parent) {
64128 			DUK_ASSERT(DUK_CAT_GET_TYPE(tmp_cat) == DUK_CAT_TYPE_LABEL); /* a non-catching entry */
64129 		}
64130 	}
64131 #endif  /* DUK_USE_ASSERTIONS */
64132 
64133 	/*
64134 	 *  Store entry state.
64135 	 */
64136 
64137 #if defined(DUK_USE_ASSERTIONS)
64138 	entry_act = thr->callstack_curr;
64139 	entry_callstack_top = thr->callstack_top;
64140 #endif
64141 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64142 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64143 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
64144 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
64145 	entry_thread_state = thr->state;
64146 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
64147 
64148 	/* If thr->ptr_curr_pc is set, sync curr_pc to act->pc.  Then NULL
64149 	 * thr->ptr_curr_pc so that it's not accidentally used with an incorrect
64150 	 * activation when side effects occur.
64151 	 */
64152 	duk_hthread_sync_and_null_currpc(thr);
64153 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
64154 
64155 	DUK_DD(DUK_DDPRINT("duk__handle_call_raw: thr=%p, idx_func=%ld, "
64156 	                   "call_flags=0x%08lx (constructor=%ld), "
64157 	                   "valstack_top=%ld, idx_func=%ld, idx_args=%ld, rec_depth=%ld/%ld, "
64158 	                   "entry_valstack_bottom_byteoff=%ld, entry_valstack_end_byteoff=%ld, "
64159 	                   "entry_call_recursion_depth=%ld, "
64160 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
64161 	                   (void *) thr,
64162 	                   (long) idx_func,
64163 	                   (unsigned long) call_flags,
64164 	                   (long) ((call_flags & DUK_CALL_FLAG_CONSTRUCT) != 0 ? 1 : 0),
64165 	                   (long) duk_get_top(thr),
64166 	                   (long) idx_func,
64167 	                   (long) (idx_func + 2),
64168 	                   (long) thr->heap->call_recursion_depth,
64169 	                   (long) thr->heap->call_recursion_limit,
64170 	                   (long) entry_valstack_bottom_byteoff,
64171 	                   (long) entry_valstack_end_byteoff,
64172 	                   (long) entry_call_recursion_depth,
64173 	                   (void *) entry_curr_thread,
64174 	                   (long) entry_thread_state));
64175 
64176 	/*
64177 	 *  Thread state check and book-keeping.
64178 	 */
64179 
64180 	duk__call_thread_state_update(thr);
64181 
64182 	/*
64183 	 *  Resolve final target function; handle bound functions and special
64184 	 *  functions like .call() and .apply().  Also figure out the effective
64185 	 *  'this' binding, which replaces the current value at idx_func + 1.
64186 	 */
64187 
64188 	if (DUK_LIKELY(duk__resolve_target_fastpath_check(thr, idx_func, &func, call_flags) != 0U)) {
64189 		DUK_DDD(DUK_DDDPRINT("fast path target resolve"));
64190 	} else {
64191 		DUK_DDD(DUK_DDDPRINT("slow path target resolve"));
64192 		func = duk__resolve_target_func_and_this_binding(thr, idx_func, &call_flags);
64193 	}
64194 	DUK_ASSERT(duk_get_top(thr) - idx_func >= 2);  /* at least func and this present */
64195 
64196 	DUK_ASSERT(func == NULL || !DUK_HOBJECT_HAS_BOUNDFUNC(func));
64197 	DUK_ASSERT(func == NULL || (DUK_HOBJECT_IS_COMPFUNC(func) ||
64198 	                            DUK_HOBJECT_IS_NATFUNC(func)));
64199 
64200 	/* [ ... func this arg1 ... argN ] */
64201 
64202 	/*
64203 	 *  Setup a preliminary activation and figure out nargs/nregs and
64204 	 *  value stack minimum size.
64205 	 *
64206 	 *  Don't touch valstack_bottom or valstack_top yet so that Duktape API
64207 	 *  calls work normally.
64208 	 *
64209 	 *  Because 'act' is not zeroed, all fields must be filled in.
64210 	 */
64211 
64212 	/* Should not be necessary, but initialize to silence warnings. */
64213 	act = NULL;
64214 	nargs = 0;
64215 	nregs = 0;
64216 	vs_min_bytes = 0;
64217 
64218 #if defined(DUK_USE_TAILCALL)
64219 	use_tailcall = (call_flags & DUK_CALL_FLAG_TAILCALL);
64220 	if (use_tailcall) {
64221 		use_tailcall = duk__call_setup_act_attempt_tailcall(thr,
64222 		                                                    call_flags,
64223 		                                                    idx_func,
64224 		                                                    func,
64225 		                                                    entry_valstack_bottom_byteoff,
64226 		                                                    entry_valstack_end_byteoff,
64227 		                                                    &nargs,
64228 		                                                    &nregs,
64229 		                                                    &vs_min_bytes,
64230 		                                                    &act);
64231 	}
64232 #else
64233 	DUK_ASSERT((call_flags & DUK_CALL_FLAG_TAILCALL) == 0);  /* compiler ensures this */
64234 	use_tailcall = 0;
64235 #endif
64236 
64237 	if (use_tailcall) {
64238 		idx_args = 0;
64239 		DUK_STATS_INC(thr->heap, stats_call_tailcall);
64240 	} else {
64241 		duk__call_setup_act_not_tailcall(thr,
64242 		                                 call_flags,
64243 		                                 idx_func,
64244 		                                 func,
64245 		                                 entry_valstack_bottom_byteoff,
64246 		                                 entry_valstack_end_byteoff,
64247 		                                 &nargs,
64248 		                                 &nregs,
64249 		                                 &vs_min_bytes,
64250 		                                 &act);
64251 		idx_args = idx_func + 2;
64252 	}
64253 	/* After this point idx_func is no longer valid for tailcalls. */
64254 
64255 	DUK_ASSERT(act != NULL);
64256 
64257 	/* [ ... func this arg1 ... argN ] */
64258 
64259 	/*
64260 	 *  Environment record creation and 'arguments' object creation.
64261 	 *  Named function expression name binding is handled by the
64262 	 *  compiler; the compiled function's parent env will contain
64263 	 *  the (immutable) binding already.
64264 	 *
64265 	 *  This handling is now identical for C and ECMAScript functions.
64266 	 *  C functions always have the 'NEWENV' flag set, so their
64267 	 *  environment record initialization is delayed (which is good).
64268 	 *
64269 	 *  Delayed creation (on demand) is handled in duk_js_var.c.
64270 	 */
64271 
64272 	duk__call_env_setup(thr, func, act, idx_args);
64273 
64274 	/* [ ... func this arg1 ... argN ] */
64275 
64276 	/*
64277 	 *  Setup value stack: clamp to 'nargs', fill up to 'nregs',
64278 	 *  ensure value stack size matches target requirements, and
64279 	 *  switch value stack bottom.  Valstack top is kept.
64280 	 *
64281 	 *  Value stack can only grow here.
64282 	 */
64283 
64284 	duk_valstack_grow_check_throw(thr, vs_min_bytes);
64285 	act->reserve_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64286 
64287 	if (use_tailcall) {
64288 		DUK_ASSERT(nregs >= 0);
64289 		DUK_ASSERT(nregs >= nargs);
64290 		duk_set_top_and_wipe(thr, nregs, nargs);
64291 	} else {
64292 		if (nregs >= 0) {
64293 			DUK_ASSERT(nregs >= nargs);
64294 			duk_set_top_and_wipe(thr, idx_func + 2 + nregs, idx_func + 2 + nargs);
64295 		} else {
64296 			;
64297 		}
64298 		thr->valstack_bottom = thr->valstack_bottom + idx_func + 2;
64299 	}
64300 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64301 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64302 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64303 
64304 	/*
64305 	 *  Make the actual call.  For Ecma-to-Ecma calls detect that
64306 	 *  setup is complete, then return with a status code that allows
64307 	 *  the caller to reuse the running executor.
64308 	 */
64309 
64310 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
64311 		/*
64312 		 *  ECMAScript call.
64313 		 */
64314 
64315 		DUK_ASSERT(func != NULL);
64316 		DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(func));
64317 		act->curr_pc = DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, (duk_hcompfunc *) func);
64318 
64319 		if (call_flags & DUK_CALL_FLAG_ALLOW_ECMATOECMA) {
64320 			DUK_DD(DUK_DDPRINT("avoid native call, use existing executor"));
64321 			DUK_STATS_INC(thr->heap, stats_call_ecmatoecma);
64322 			DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64323 			DUK_REFZERO_CHECK_FAST(thr);
64324 			DUK_ASSERT(thr->ptr_curr_pc == NULL);
64325 			return 1;  /* 1=reuse executor */
64326 		}
64327 		DUK_ASSERT(use_tailcall == 0);
64328 
64329 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64330 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64331 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64332 		thr->callstack_preventcount++;
64333 
64334 		/* XXX: we could just do this on entry regardless of reuse, as long
64335 		 * as recursion depth is decreased for e2e case.
64336 		 */
64337 		duk__call_c_recursion_limit_check(thr);
64338 		thr->heap->call_recursion_depth++;
64339 
64340 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64341 
64342 		/*
64343 		 *  Bytecode executor call.
64344 		 *
64345 		 *  Execute bytecode, handling any recursive function calls and
64346 		 *  thread resumptions.  Returns when execution would return from
64347 		 *  the entry level activation.  When the executor returns, a
64348 		 *  single return value is left on the stack top.
64349 		 *
64350 		 *  The only possible longjmp() is an error (DUK_LJ_TYPE_THROW),
64351 		 *  other types are handled internally by the executor.
64352 		 */
64353 
64354 		/* thr->ptr_curr_pc is set by bytecode executor early on entry */
64355 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64356 		DUK_DDD(DUK_DDDPRINT("entering bytecode execution"));
64357 		duk_js_execute_bytecode(thr);
64358 		DUK_DDD(DUK_DDDPRINT("returned from bytecode execution"));
64359 	} else {
64360 		/*
64361 		 *  Native call.
64362 		 */
64363 
64364 		DUK_ASSERT(func == NULL || ((duk_hnatfunc *) func)->func != NULL);
64365 		DUK_ASSERT(use_tailcall == 0);
64366 
64367 		/* [ ... func this | arg1 ... argN ] ('this' must precede new bottom) */
64368 
64369 		/* duk_hthread_activation_unwind_norz() will decrease this on unwind */
64370 		DUK_ASSERT((act->flags & DUK_ACT_FLAG_PREVENT_YIELD) == 0);
64371 		act->flags |= DUK_ACT_FLAG_PREVENT_YIELD;
64372 		thr->callstack_preventcount++;
64373 
64374 		/* XXX: we could just do this on entry regardless of reuse, as long
64375 		 * as recursion depth is decreased for e2e case.
64376 		 */
64377 		duk__call_c_recursion_limit_check(thr);
64378 		thr->heap->call_recursion_depth++;
64379 
64380 		/* For native calls must be NULL so we don't sync back */
64381 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
64382 
64383 		/* XXX: native funcptr could come out of call setup. */
64384 		if (func) {
64385 			rc = ((duk_hnatfunc *) func)->func(thr);
64386 		} else {
64387 			duk_tval *tv_func;
64388 			duk_c_function funcptr;
64389 
64390 			tv_func = &act->tv_func;
64391 			DUK_ASSERT(DUK_TVAL_IS_LIGHTFUNC(tv_func));
64392 			funcptr = DUK_TVAL_GET_LIGHTFUNC_FUNCPTR(tv_func);
64393 			rc = funcptr(thr);
64394 		}
64395 
64396 		/* Automatic error throwing, retval check. */
64397 
64398 		if (rc == 0) {
64399 			DUK_ASSERT(thr->valstack < thr->valstack_end);
64400 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
64401 			thr->valstack_top++;
64402 		} else if (rc == 1) {
64403 			;
64404 		} else if (rc < 0) {
64405 			duk_error_throw_from_negative_rc(thr, rc);
64406 			DUK_WO_NORETURN(return 0;);
64407 		} else {
64408 			DUK_ERROR_TYPE(thr, DUK_STR_INVALID_CFUNC_RC);
64409 			DUK_WO_NORETURN(return 0;);
64410 		}
64411 	}
64412 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
64413 	DUK_ASSERT(use_tailcall == 0);
64414 
64415 	/*
64416 	 *  Constructor call post processing.
64417 	 */
64418 
64419 #if defined(DUK_USE_ES6_PROXY)
64420 	if (call_flags & (DUK_CALL_FLAG_CONSTRUCT | DUK_CALL_FLAG_CONSTRUCT_PROXY)) {
64421 		duk_call_construct_postprocess(thr, call_flags & DUK_CALL_FLAG_CONSTRUCT_PROXY);
64422 	}
64423 #else
64424 	if (call_flags & DUK_CALL_FLAG_CONSTRUCT) {
64425 		duk_call_construct_postprocess(thr, 0);
64426 	}
64427 #endif
64428 
64429 	/*
64430 	 *  Unwind, restore valstack bottom and other book-keeping.
64431 	 */
64432 
64433 	DUK_ASSERT(thr->callstack_curr != NULL);
64434 	DUK_ASSERT(thr->callstack_curr->parent == entry_act);
64435 	DUK_ASSERT(thr->callstack_top == entry_callstack_top + 1);
64436 	duk_hthread_activation_unwind_norz(thr);
64437 	DUK_ASSERT(thr->callstack_curr == entry_act);
64438 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64439 
64440 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
64441 	/* keep current valstack_top */
64442 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64443 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64444 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64445 	DUK_ASSERT(thr->valstack_top - thr->valstack_bottom >= idx_func + 1);
64446 
64447 	/* Return value handling. */
64448 
64449 	/* [ ... func this (crud) retval ] */
64450 
64451 	{
64452 		duk_tval *tv_ret;
64453 		duk_tval *tv_funret;
64454 
64455 		tv_ret = thr->valstack_bottom + idx_func;
64456 		tv_funret = thr->valstack_top - 1;
64457 #if defined(DUK_USE_FASTINT)
64458 		/* Explicit check for fastint downgrade. */
64459 		DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
64460 #endif
64461 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret);  /* side effects */
64462 	}
64463 
64464 	duk_set_top_unsafe(thr, idx_func + 1);
64465 
64466 	/* [ ... retval ] */
64467 
64468 	/* Restore caller's value stack reserve (cannot fail). */
64469 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff >= (duk_uint8_t *) thr->valstack_top);
64470 	DUK_ASSERT((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff <= (duk_uint8_t *) thr->valstack_alloc_end);
64471 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_end_byteoff);
64472 
64473 	/* XXX: Trial value stack shrink would be OK here, but we'd need
64474 	 * to prevent side effects of the potential realloc.
64475 	 */
64476 
64477 	/* Restore entry thread executor curr_pc stack frame pointer. */
64478 	thr->ptr_curr_pc = entry_ptr_curr_pc;
64479 
64480 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64481 	thr->state = (duk_uint8_t) entry_thread_state;
64482 
64483 	/* Disabled assert: triggered with some torture tests. */
64484 #if 0
64485 	DUK_ASSERT((thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread == NULL) ||  /* first call */
64486 	           (thr->state == DUK_HTHREAD_STATE_INACTIVE && thr->heap->curr_thread != NULL) ||  /* other call */
64487 	           (thr->state == DUK_HTHREAD_STATE_RUNNING && thr->heap->curr_thread == thr));     /* current thread */
64488 #endif
64489 
64490 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
64491 
64492 	/* If the debugger is active we need to force an interrupt so that
64493 	 * debugger breakpoints are rechecked.  This is important for function
64494 	 * calls caused by side effects (e.g. when doing a DUK_OP_GETPROP), see
64495 	 * GH-303.  Only needed for success path, error path always causes a
64496 	 * breakpoint recheck in the executor.  It would be enough to set this
64497 	 * only when returning to an ECMAScript activation, but setting the flag
64498 	 * on every return should have no ill effect.
64499 	 */
64500 #if defined(DUK_USE_DEBUGGER_SUPPORT)
64501 	if (duk_debug_is_attached(thr->heap)) {
64502 		DUK_DD(DUK_DDPRINT("returning with debugger enabled, force interrupt"));
64503 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
64504 		thr->interrupt_init -= thr->interrupt_counter;
64505 		thr->interrupt_counter = 0;
64506 		thr->heap->dbg_force_restart = 1;
64507 	}
64508 #endif
64509 
64510 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
64511 	duk__interrupt_fixup(thr, entry_curr_thread);
64512 #endif
64513 
64514 	/* Restored by success path. */
64515 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
64516 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
64517 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64518 
64519 	DUK_REFZERO_CHECK_FAST(thr);
64520 
64521 	return 0;  /* 0=call handled inline */
64522 }
64523 
64524 DUK_INTERNAL duk_int_t duk_handle_call_unprotected_nargs(duk_hthread *thr,
64525                                                          duk_idx_t nargs,
64526                                                          duk_small_uint_t call_flags) {
64527 	duk_idx_t idx_func;
64528 	DUK_ASSERT(duk_get_top(thr) >= nargs + 2);
64529 	idx_func = duk_get_top(thr) - (nargs + 2);
64530 	DUK_ASSERT(idx_func >= 0);
64531 	return duk_handle_call_unprotected(thr, idx_func, call_flags);
64532 }
64533 
64534 DUK_INTERNAL duk_int_t duk_handle_call_unprotected(duk_hthread *thr,
64535                                                    duk_idx_t idx_func,
64536                                                    duk_small_uint_t call_flags) {
64537 	DUK_ASSERT(duk_is_valid_index(thr, idx_func));
64538 	DUK_ASSERT(idx_func >= 0);
64539 	return duk__handle_call_raw(thr, idx_func, call_flags);
64540 }
64541 
64542 /*
64543  *  duk_handle_safe_call(): make a "C protected call" within the
64544  *  current activation.
64545  *
64546  *  The allowed thread states for making a call are the same as for
64547  *  duk_handle_call_protected().
64548  *
64549  *  Even though this call is protected, errors are thrown for insane arguments
64550  *  and may result in a fatal error unless there's another protected call which
64551  *  catches such errors.
64552  *
64553  *  The error handling path should be error free, even for out-of-memory
64554  *  errors, to ensure safe sandboxing.  (As of Duktape 2.2.0 this is not
64555  *  yet the case for environment closing which may run out of memory, see
64556  *  XXX notes below.)
64557  */
64558 
64559 DUK_LOCAL void duk__handle_safe_call_inner(duk_hthread *thr,
64560                                            duk_safe_call_function func,
64561                                            void *udata,
64562 #if defined(DUK_USE_ASSERTIONS)
64563                                            duk_size_t entry_valstack_bottom_byteoff,
64564                                            duk_size_t entry_callstack_top,
64565 #endif
64566                                            duk_hthread *entry_curr_thread,
64567                                            duk_uint_fast8_t entry_thread_state,
64568                                            duk_idx_t idx_retbase,
64569                                            duk_idx_t num_stack_rets) {
64570 	duk_ret_t rc;
64571 
64572 	DUK_ASSERT(thr != NULL);
64573 	DUK_ASSERT_CTX_VALID(thr);
64574 
64575 	/*
64576 	 *  Thread state check and book-keeping.
64577 	 */
64578 
64579 	duk__call_thread_state_update(thr);
64580 
64581 	/*
64582 	 *  Recursion limit check.
64583 	 */
64584 
64585 	duk__call_c_recursion_limit_check(thr);
64586 	thr->heap->call_recursion_depth++;
64587 
64588 	/*
64589 	 *  Make the C call.
64590 	 */
64591 
64592 	rc = func(thr, udata);
64593 
64594 	DUK_DDD(DUK_DDDPRINT("safe_call, func rc=%ld", (long) rc));
64595 
64596 	/*
64597 	 *  Valstack manipulation for results.
64598 	 */
64599 
64600 	/* we're running inside the caller's activation, so no change in call/catch stack or valstack bottom */
64601 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64602 	DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
64603 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
64604 	DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
64605 	DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
64606 
64607 	if (DUK_UNLIKELY(rc < 0)) {
64608 		duk_error_throw_from_negative_rc(thr, rc);
64609 		DUK_WO_NORETURN(return;);
64610 	}
64611 	DUK_ASSERT(rc >= 0);
64612 
64613 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, rc);  /* throws for insane rc */
64614 
64615 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64616 	thr->state = (duk_uint8_t) entry_thread_state;
64617 }
64618 
64619 DUK_LOCAL void duk__handle_safe_call_error(duk_hthread *thr,
64620                                            duk_activation *entry_act,
64621 #if defined(DUK_USE_ASSERTIONS)
64622                                            duk_size_t entry_callstack_top,
64623 #endif
64624                                            duk_hthread *entry_curr_thread,
64625                                            duk_uint_fast8_t entry_thread_state,
64626                                            duk_idx_t idx_retbase,
64627                                            duk_idx_t num_stack_rets,
64628                                            duk_size_t entry_valstack_bottom_byteoff,
64629                                            duk_jmpbuf *old_jmpbuf_ptr) {
64630 	DUK_ASSERT(thr != NULL);
64631 	DUK_ASSERT_CTX_VALID(thr);
64632 
64633 	/*
64634 	 *  Error during call.  The error value is at heap->lj.value1.
64635 	 *
64636 	 *  The very first thing we do is restore the previous setjmp catcher.
64637 	 *  This means that any error in error handling will propagate outwards
64638 	 *  instead of causing a setjmp() re-entry above.
64639 	 */
64640 
64641 	DUK_DDD(DUK_DDDPRINT("error caught during protected duk_handle_safe_call()"));
64642 
64643 	/* Other longjmp types are handled by executor before propagating
64644 	 * the error here.
64645 	 */
64646 	DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);
64647 	DUK_ASSERT_LJSTATE_SET(thr->heap);
64648 
64649 	/* Either pointer may be NULL (at entry), so don't assert. */
64650 	thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
64651 
64652 	/* XXX: callstack unwind may now throw an error when closing
64653 	 * scopes; this is a sandboxing issue, described in:
64654 	 * https://github.com/svaarala/duktape/issues/476
64655 	 */
64656 	/* XXX: "unwind to" primitive? */
64657 
64658 	DUK_ASSERT(thr->callstack_top >= entry_callstack_top);
64659 	while (thr->callstack_curr != entry_act) {
64660 		DUK_ASSERT(thr->callstack_curr != NULL);
64661 		duk_hthread_activation_unwind_norz(thr);
64662 	}
64663 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64664 
64665 	/* Switch active thread before any side effects to avoid a
64666 	 * dangling curr_thread pointer.
64667 	 */
64668 	DUK_HEAP_SWITCH_THREAD(thr->heap, entry_curr_thread);  /* may be NULL */
64669 	thr->state = (duk_uint8_t) entry_thread_state;
64670 
64671 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
64672 	DUK_ASSERT(thr->state == entry_thread_state);
64673 
64674 	/* Restore valstack bottom. */
64675 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + entry_valstack_bottom_byteoff);
64676 
64677 	/* [ ... | (crud) ] */
64678 
64679 	/* XXX: ensure space in valstack (now relies on internal reserve)? */
64680 	duk_push_tval(thr, &thr->heap->lj.value1);
64681 
64682 	/* [ ... | (crud) errobj ] */
64683 
64684 	DUK_ASSERT(duk_get_top(thr) >= 1);  /* at least errobj must be on stack */
64685 
64686 	duk__safe_call_adjust_valstack(thr, idx_retbase, num_stack_rets, 1);  /* 1 = num actual 'return values' */
64687 
64688 	/* [ ... | ] or [ ... | errobj (M * undefined)] where M = num_stack_rets - 1 */
64689 
64690 	/* Reset longjmp state. */
64691 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
64692 	thr->heap->lj.iserror = 0;
64693 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value1);
64694 	DUK_TVAL_SET_UNDEFINED_UPDREF_NORZ(thr, &thr->heap->lj.value2);
64695 
64696 	/* Error handling complete, remove side effect protections.  Caller
64697 	 * will process pending finalizers.
64698 	 */
64699 #if defined(DUK_USE_ASSERTIONS)
64700 	DUK_ASSERT(thr->heap->error_not_allowed == 1);
64701 	thr->heap->error_not_allowed = 0;
64702 #endif
64703 	DUK_ASSERT(thr->heap->pf_prevent_count > 0);
64704 	thr->heap->pf_prevent_count--;
64705 	DUK_DD(DUK_DDPRINT("safe call error handled, pf_prevent_count updated to %ld", (long) thr->heap->pf_prevent_count));
64706 
64707 	/* thr->ptr_curr_pc is restored by
64708 	 * duk__handle_safe_call_shared_unwind() which is also used for
64709 	 * success path.
64710 	 */
64711 }
64712 
64713 DUK_LOCAL void duk__handle_safe_call_shared_unwind(duk_hthread *thr,
64714                                                    duk_idx_t idx_retbase,
64715                                                    duk_idx_t num_stack_rets,
64716 #if defined(DUK_USE_ASSERTIONS)
64717                                                    duk_size_t entry_callstack_top,
64718 #endif
64719                                                    duk_int_t entry_call_recursion_depth,
64720                                                    duk_hthread *entry_curr_thread,
64721                                                    duk_instr_t **entry_ptr_curr_pc) {
64722 	DUK_ASSERT(thr != NULL);
64723 	DUK_ASSERT_CTX_VALID(thr);
64724 	DUK_UNREF(idx_retbase);
64725 	DUK_UNREF(num_stack_rets);
64726 	DUK_UNREF(entry_curr_thread);
64727 
64728 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64729 
64730 	/* Restore entry thread executor curr_pc stack frame pointer.
64731 	 * XXX: would be enough to do in error path only, should nest
64732 	 * cleanly in success path.
64733 	 */
64734 	thr->ptr_curr_pc = entry_ptr_curr_pc;
64735 
64736 	thr->heap->call_recursion_depth = entry_call_recursion_depth;
64737 
64738 	/* stack discipline consistency check */
64739 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
64740 
64741 	/* A debugger forced interrupt check is not needed here, as
64742 	 * problematic safe calls are not caused by side effects.
64743 	 */
64744 
64745 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
64746 	duk__interrupt_fixup(thr, entry_curr_thread);
64747 #endif
64748 }
64749 
64750 DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
64751                                             duk_safe_call_function func,
64752                                             void *udata,
64753                                             duk_idx_t num_stack_args,
64754                                             duk_idx_t num_stack_rets) {
64755 	duk_activation *entry_act;
64756 	duk_size_t entry_valstack_bottom_byteoff;
64757 #if defined(DUK_USE_ASSERTIONS)
64758 	duk_size_t entry_valstack_end_byteoff;
64759 	duk_size_t entry_callstack_top;
64760 	duk_size_t entry_callstack_preventcount;
64761 #endif
64762 	duk_int_t entry_call_recursion_depth;
64763 	duk_hthread *entry_curr_thread;
64764 	duk_uint_fast8_t entry_thread_state;
64765 	duk_instr_t **entry_ptr_curr_pc;
64766 	duk_jmpbuf *old_jmpbuf_ptr = NULL;
64767 	duk_jmpbuf our_jmpbuf;
64768 	duk_idx_t idx_retbase;
64769 	duk_int_t retval;
64770 
64771 	DUK_ASSERT(thr != NULL);
64772 	DUK_ASSERT(duk_get_top(thr) >= num_stack_args);  /* Caller ensures. */
64773 
64774 	DUK_STATS_INC(thr->heap, stats_safecall_all);
64775 
64776 	/* Value stack reserve handling: safe call assumes caller has reserved
64777 	 * space for nrets (assuming optimal unwind processing).  Value stack
64778 	 * reserve is not stored/restored as for normal calls because a safe
64779 	 * call conceptually happens in the same activation.
64780 	 */
64781 
64782 	/* Careful with indices like '-x'; if 'x' is zero, it refers to bottom */
64783 	entry_act = thr->callstack_curr;
64784 	entry_valstack_bottom_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack);
64785 #if defined(DUK_USE_ASSERTIONS)
64786 	entry_valstack_end_byteoff = (duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack);
64787 	entry_callstack_top = thr->callstack_top;
64788 	entry_callstack_preventcount = thr->callstack_preventcount;
64789 #endif
64790 	entry_call_recursion_depth = thr->heap->call_recursion_depth;
64791 	entry_curr_thread = thr->heap->curr_thread;  /* may be NULL if first call */
64792 	entry_thread_state = thr->state;
64793 	entry_ptr_curr_pc = thr->ptr_curr_pc;  /* may be NULL */
64794 	idx_retbase = duk_get_top(thr) - num_stack_args;  /* not a valid stack index if num_stack_args == 0 */
64795 	DUK_ASSERT(idx_retbase >= 0);
64796 
64797 	DUK_ASSERT((duk_idx_t) (thr->valstack_top - thr->valstack_bottom) >= num_stack_args);  /* Caller ensures. */
64798 	DUK_ASSERT((duk_idx_t) (thr->valstack_end - (thr->valstack_bottom + idx_retbase)) >= num_stack_rets);  /* Caller ensures. */
64799 
64800 	/* Cannot portably debug print a function pointer, hence 'func' not printed! */
64801 	DUK_DD(DUK_DDPRINT("duk_handle_safe_call: thr=%p, num_stack_args=%ld, num_stack_rets=%ld, "
64802 	                   "valstack_top=%ld, idx_retbase=%ld, rec_depth=%ld/%ld, "
64803 	                   "entry_act=%p, entry_valstack_bottom_byteoff=%ld, entry_call_recursion_depth=%ld, "
64804 	                   "entry_curr_thread=%p, entry_thread_state=%ld",
64805 	                   (void *) thr,
64806 	                   (long) num_stack_args,
64807 	                   (long) num_stack_rets,
64808 	                   (long) duk_get_top(thr),
64809 	                   (long) idx_retbase,
64810 	                   (long) thr->heap->call_recursion_depth,
64811 	                   (long) thr->heap->call_recursion_limit,
64812 	                   (void *) entry_act,
64813 	                   (long) entry_valstack_bottom_byteoff,
64814 	                   (long) entry_call_recursion_depth,
64815 	                   (void *) entry_curr_thread,
64816 	                   (long) entry_thread_state));
64817 
64818 	/* Setjmp catchpoint setup. */
64819 	old_jmpbuf_ptr = thr->heap->lj.jmpbuf_ptr;
64820 	thr->heap->lj.jmpbuf_ptr = &our_jmpbuf;
64821 
64822 	/* Prevent yields for the duration of the safe call.  This only
64823 	 * matters if the executor makes safe calls to functions that
64824 	 * yield, this doesn't currently happen.
64825 	 */
64826 	thr->callstack_preventcount++;
64827 
64828 #if defined(DUK_USE_CPP_EXCEPTIONS)
64829 	try {
64830 #else
64831 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == &our_jmpbuf);
64832 	if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
64833 		/* Success path. */
64834 #endif
64835 		DUK_DDD(DUK_DDDPRINT("safe_call setjmp catchpoint setup complete"));
64836 
64837 		duk__handle_safe_call_inner(thr,
64838 		                            func,
64839 		                            udata,
64840 #if defined(DUK_USE_ASSERTIONS)
64841 		                            entry_valstack_bottom_byteoff,
64842 		                            entry_callstack_top,
64843 #endif
64844 		                            entry_curr_thread,
64845 		                            entry_thread_state,
64846 		                            idx_retbase,
64847 		                            num_stack_rets);
64848 
64849 		DUK_STATS_INC(thr->heap, stats_safecall_nothrow);
64850 
64851 		/* Either pointer may be NULL (at entry), so don't assert */
64852 		thr->heap->lj.jmpbuf_ptr = old_jmpbuf_ptr;
64853 
64854 		/* If calls happen inside the safe call, these are restored by
64855 		 * whatever calls are made.  Reserve cannot decrease.
64856 		 */
64857 		DUK_ASSERT(thr->callstack_curr == entry_act);
64858 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64859 
64860 		retval = DUK_EXEC_SUCCESS;
64861 #if defined(DUK_USE_CPP_EXCEPTIONS)
64862 	} catch (duk_internal_exception &exc) {
64863 		DUK_UNREF(exc);
64864 #else
64865 	} else {
64866 		/* Error path. */
64867 #endif
64868 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64869 
64870 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64871 
64872 		duk__handle_safe_call_error(thr,
64873 		                            entry_act,
64874 #if defined(DUK_USE_ASSERTIONS)
64875 		                            entry_callstack_top,
64876 #endif
64877 		                            entry_curr_thread,
64878 		                            entry_thread_state,
64879 		                            idx_retbase,
64880 		                            num_stack_rets,
64881 		                            entry_valstack_bottom_byteoff,
64882 		                            old_jmpbuf_ptr);
64883 
64884 		retval = DUK_EXEC_ERROR;
64885 	}
64886 #if defined(DUK_USE_CPP_EXCEPTIONS)
64887 	catch (duk_fatal_exception &exc) {
64888 		DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
64889 		throw;
64890 	} catch (std::exception &exc) {
64891 		const char *what = exc.what();
64892 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64893 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64894 		if (!what) {
64895 			what = "unknown";
64896 		}
64897 		DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
64898 		try {
64899 			DUK_ERROR_FMT1(thr, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
64900 			DUK_WO_NORETURN(return 0;);
64901 		} catch (duk_internal_exception exc) {
64902 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
64903 			DUK_UNREF(exc);
64904 			duk__handle_safe_call_error(thr,
64905 			                            entry_act,
64906 #if defined(DUK_USE_ASSERTIONS)
64907 			                            entry_callstack_top,
64908 #endif
64909 			                            entry_curr_thread,
64910 			                            entry_thread_state,
64911 			                            idx_retbase,
64912 			                            num_stack_rets,
64913 			                            entry_valstack_bottom_byteoff,
64914 			                            old_jmpbuf_ptr);
64915 			retval = DUK_EXEC_ERROR;
64916 		}
64917 	} catch (...) {
64918 		DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
64919 		DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64920 		DUK_STATS_INC(thr->heap, stats_safecall_throw);
64921 		try {
64922 			DUK_ERROR_TYPE(thr, "caught invalid c++ exception (perhaps thrown by user code)");
64923 			DUK_WO_NORETURN(return 0;);
64924 		} catch (duk_internal_exception exc) {
64925 			DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
64926 			DUK_UNREF(exc);
64927 			duk__handle_safe_call_error(thr,
64928 			                            entry_act,
64929 #if defined(DUK_USE_ASSERTIONS)
64930 			                            entry_callstack_top,
64931 #endif
64932 			                            entry_curr_thread,
64933 			                            entry_thread_state,
64934 			                            idx_retbase,
64935 			                            num_stack_rets,
64936 			                            entry_valstack_bottom_byteoff,
64937 			                            old_jmpbuf_ptr);
64938 			retval = DUK_EXEC_ERROR;
64939 		}
64940 	}
64941 #endif
64942 
64943 	DUK_ASSERT(thr->heap->lj.jmpbuf_ptr == old_jmpbuf_ptr);  /* success/error path both do this */
64944 
64945 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64946 
64947 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64948 	duk__handle_safe_call_shared_unwind(thr,
64949 	                                    idx_retbase,
64950 	                                    num_stack_rets,
64951 #if defined(DUK_USE_ASSERTIONS)
64952 	                                    entry_callstack_top,
64953 #endif
64954 	                                    entry_call_recursion_depth,
64955 	                                    entry_curr_thread,
64956 	                                    entry_ptr_curr_pc);
64957 
64958 	/* Restore preventcount. */
64959 	thr->callstack_preventcount--;
64960 	DUK_ASSERT(thr->callstack_preventcount == entry_callstack_preventcount);
64961 
64962 	/* Final asserts. */
64963 	DUK_ASSERT(thr->callstack_curr == entry_act);
64964 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_bottom - (duk_uint8_t *) thr->valstack) == entry_valstack_bottom_byteoff);
64965 	DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
64966 	DUK_ASSERT(thr->callstack_top == entry_callstack_top);
64967 	DUK_ASSERT(thr->heap->call_recursion_depth == entry_call_recursion_depth);
64968 	DUK_ASSERT(thr->heap->curr_thread == entry_curr_thread);
64969 	DUK_ASSERT(thr->state == entry_thread_state);
64970 	DUK_ASSERT(thr->ptr_curr_pc == entry_ptr_curr_pc);
64971 	DUK_ASSERT(duk_get_top(thr) == idx_retbase + num_stack_rets);
64972 	DUK_ASSERT_LJSTATE_UNSET(thr->heap);
64973 
64974 	/* Pending side effects. */
64975 	DUK_REFZERO_CHECK_FAST(thr);
64976 
64977 	return retval;
64978 }
64979 
64980 /*
64981  *  Property-based call (foo.noSuch()) error setup: replace target function
64982  *  on stack top with a specially tagged (hidden Symbol) error which gets
64983  *  thrown in call handling at the proper spot to follow ECMAScript semantics.
64984  */
64985 
64986 #if defined(DUK_USE_VERBOSE_ERRORS)
64987 DUK_INTERNAL DUK_NOINLINE DUK_COLD void duk_call_setup_propcall_error(duk_hthread *thr, duk_tval *tv_targ, duk_tval *tv_base, duk_tval *tv_key) {
64988 	const char *str1, *str2, *str3;
64989 	duk_idx_t entry_top;
64990 
64991 	entry_top = duk_get_top(thr);
64992 
64993 	/* Must stabilize pointers first.  Argument convention is a bit awkward,
64994 	 * it comes from the executor call site where some arguments may not be
64995 	 * on the value stack (consts).
64996 	 */
64997 	duk_push_tval(thr, tv_base);
64998 	duk_push_tval(thr, tv_key);
64999 	duk_push_tval(thr, tv_targ);
65000 
65001 	DUK_GC_TORTURE(thr->heap);
65002 
65003 	/* We only push an error, replacing the call target (at idx_func)
65004 	 * with the error to ensure side effects come out correctly:
65005 	 * - Property read
65006 	 * - Call argument evaluation
65007 	 * - Callability check and error thrown.
65008 	 *
65009 	 * A hidden Symbol on the error object pushed here is used by
65010 	 * call handling to figure out the error is to be thrown as is.
65011 	 * It is CRITICAL that the hidden Symbol can never occur on a
65012 	 * user visible object that may get thrown.
65013 	 */
65014 
65015 #if defined(DUK_USE_PARANOID_ERRORS)
65016 	str1 = duk_get_type_name(thr, -1);
65017 	str2 = duk_get_type_name(thr, -2);
65018 	str3 = duk_get_type_name(thr, -3);
65019 	duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
65020 #else
65021 	str1 = duk_push_string_readable(thr, -1);
65022 	str2 = duk_push_string_readable(thr, -3);
65023 	str3 = duk_push_string_readable(thr, -5);
65024 	duk_push_error_object(thr, DUK_ERR_TYPE_ERROR | DUK_ERRCODE_FLAG_NOBLAME_FILELINE, "%s not callable (property %s of %s)", str1, str2, str3);
65025 #endif
65026 
65027 	duk_push_true(thr);
65028 	duk_put_prop_stridx(thr, -2, DUK_STRIDX_INT_TARGET);  /* Marker property, reuse _Target. */
65029 
65030 	/* [ <nregs> propValue <variable> error ] */
65031 	duk_replace(thr, entry_top - 1);
65032 	duk_set_top(thr, entry_top);
65033 
65034 	DUK_ASSERT(!duk_is_callable(thr, -1));  /* Critical so that call handling will throw the error. */
65035 }
65036 #endif  /* DUK_USE_VERBOSE_ERRORS */
65037 
65038 /* automatic undefs */
65039 #undef DUK__AUGMENT_CALL_RELAX_COUNT
65040 #line 1 "duk_js_compiler.c"
65041 /*
65042  *  ECMAScript compiler.
65043  *
65044  *  Parses an input string and generates a function template result.
65045  *  Compilation may happen in multiple contexts (global code, eval
65046  *  code, function code).
65047  *
65048  *  The parser uses a traditional top-down recursive parsing for the
65049  *  statement level, and an operator precedence based top-down approach
65050  *  for the expression level.  The attempt is to minimize the C stack
65051  *  depth.  Bytecode is generated directly without an intermediate
65052  *  representation (tree), at the cost of needing two (and sometimes
65053  *  three) passes over each function.
65054  *
65055  *  The top-down recursive parser functions are named "duk__parse_XXX".
65056  *
65057  *  Recursion limits are in key functions to prevent arbitrary C recursion:
65058  *  function body parsing, statement parsing, and expression parsing.
65059  *
65060  *  See doc/compiler.rst for discussion on the design.
65061  *
65062  *  A few typing notes:
65063  *
65064  *    - duk_regconst_t: signed, highest bit set (< 0) means constant,
65065  *      some call sites use -1 for "none" (equivalent to constant 0x7fffffff)
65066  *    - PC values: duk_int_t, negative values used as markers
65067  */
65068 
65069 /* #include duk_internal.h -> already included */
65070 
65071 /* If highest bit of a register number is set, it refers to a constant instead.
65072  * When interpreted as a signed value, this means const values are always
65073  * negative (when interpreted as two's complement).  For example DUK__ISREG_TEMP()
65074  * uses this approach to avoid an explicit DUK__ISREG() check (the condition is
65075  * logically "'x' is a register AND 'x' >= temp_first").
65076  */
65077 #define DUK__CONST_MARKER                   DUK_REGCONST_CONST_MARKER
65078 #define DUK__REMOVECONST(x)                 ((x) & ~DUK__CONST_MARKER)
65079 #define DUK__ISREG(x)                       ((x) >= 0)
65080 #define DUK__ISCONST(x)                     ((x) < 0)
65081 #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. */
65082 #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. */
65083 #define DUK__GETTEMP(comp_ctx)              ((comp_ctx)->curr_func.temp_next)
65084 #define DUK__SETTEMP(comp_ctx,x)            ((comp_ctx)->curr_func.temp_next = (x))  /* dangerous: must only lower (temp_max not updated) */
65085 #define DUK__SETTEMP_CHECKMAX(comp_ctx,x)   duk__settemp_checkmax((comp_ctx),(x))
65086 #define DUK__ALLOCTEMP(comp_ctx)            duk__alloctemp((comp_ctx))
65087 #define DUK__ALLOCTEMPS(comp_ctx,count)     duk__alloctemps((comp_ctx),(count))
65088 
65089 /* Init value set size for array and object literals. */
65090 #define DUK__MAX_ARRAY_INIT_VALUES        20
65091 #define DUK__MAX_OBJECT_INIT_PAIRS        10
65092 
65093 /* XXX: hack, remove when const lookup is not O(n) */
65094 #define DUK__GETCONST_MAX_CONSTS_CHECK    256
65095 
65096 /* These limits are based on bytecode limits.  Max temps is limited
65097  * by duk_hcompfunc nargs/nregs fields being 16 bits.
65098  */
65099 #define DUK__MAX_CONSTS                   DUK_BC_BC_MAX
65100 #define DUK__MAX_FUNCS                    DUK_BC_BC_MAX
65101 #define DUK__MAX_TEMPS                    0xffffL
65102 
65103 /* Initial bytecode size allocation. */
65104 #if defined(DUK_USE_PREFER_SIZE)
65105 #define DUK__BC_INITIAL_INSTS             16
65106 #else
65107 #define DUK__BC_INITIAL_INSTS             256
65108 #endif
65109 
65110 #define DUK__RECURSION_INCREASE(comp_ctx,thr)  do { \
65111 		DUK_DDD(DUK_DDDPRINT("RECURSION INCREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65112 		duk__comp_recursion_increase((comp_ctx)); \
65113 	} while (0)
65114 
65115 #define DUK__RECURSION_DECREASE(comp_ctx,thr)  do { \
65116 		DUK_DDD(DUK_DDDPRINT("RECURSION DECREASE: %s:%ld", (const char *) DUK_FILE_MACRO, (long) DUK_LINE_MACRO)); \
65117 		duk__comp_recursion_decrease((comp_ctx)); \
65118 	} while (0)
65119 
65120 /* Value stack slot limits: these are quite approximate right now, and
65121  * because they overlap in control flow, some could be eliminated.
65122  */
65123 #define DUK__COMPILE_ENTRY_SLOTS          8
65124 #define DUK__FUNCTION_INIT_REQUIRE_SLOTS  16
65125 #define DUK__FUNCTION_BODY_REQUIRE_SLOTS  16
65126 #define DUK__PARSE_STATEMENTS_SLOTS       16
65127 #define DUK__PARSE_EXPR_SLOTS             16
65128 
65129 /* Temporary structure used to pass a stack allocated region through
65130  * duk_safe_call().
65131  */
65132 typedef struct {
65133 	duk_small_uint_t flags;
65134 	duk_compiler_ctx comp_ctx_alloc;
65135 	duk_lexer_point lex_pt_alloc;
65136 } duk__compiler_stkstate;
65137 
65138 /*
65139  *  Prototypes
65140  */
65141 
65142 /* lexing */
65143 DUK_LOCAL_DECL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65144 DUK_LOCAL_DECL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect);
65145 DUK_LOCAL_DECL void duk__advance(duk_compiler_ctx *ctx);
65146 
65147 /* function helpers */
65148 DUK_LOCAL_DECL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx);
65149 DUK_LOCAL_DECL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx);
65150 DUK_LOCAL_DECL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg);
65151 DUK_LOCAL_DECL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx);
65152 DUK_LOCAL_DECL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx);
65153 
65154 /* code emission */
65155 DUK_LOCAL_DECL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx);
65156 DUK_LOCAL_DECL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc);
65157 DUK_LOCAL_DECL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins);
65158 DUK_LOCAL_DECL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op);
65159 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);
65160 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);
65161 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);
65162 #if 0  /* unused */
65163 DUK_LOCAL_DECL void duk__emit_a(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t a);
65164 DUK_LOCAL_DECL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b);
65165 #endif
65166 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);
65167 DUK_LOCAL_DECL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc);
65168 DUK_LOCAL_DECL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc);
65169 DUK_LOCAL_DECL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65170 DUK_LOCAL_DECL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val);
65171 DUK_LOCAL_DECL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc);
65172 DUK_LOCAL_DECL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx);
65173 DUK_LOCAL_DECL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65174 DUK_LOCAL_DECL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc);
65175 DUK_LOCAL_DECL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc);
65176 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);
65177 DUK_LOCAL_DECL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65178 DUK_LOCAL_DECL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst);
65179 DUK_LOCAL_DECL void duk__emit_invalid(duk_compiler_ctx *comp_ctx);
65180 
65181 /* ivalue/ispec helpers */
65182 DUK_LOCAL_DECL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst);
65183 DUK_LOCAL_DECL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65184 DUK_LOCAL_DECL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65185 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h);
65186 DUK_LOCAL_DECL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst);
65187 DUK_LOCAL_DECL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst);
65188 DUK_LOCAL_DECL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num);
65189 DUK_LOCAL_DECL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx);
65190 DUK_LOCAL_DECL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next);
65191 DUK_LOCAL_DECL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx);
65192 DUK_LOCAL_DECL
65193 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
65194                                          duk_ispec *x,
65195                                          duk_regconst_t forced_reg,
65196                                          duk_small_uint_t flags);
65197 DUK_LOCAL_DECL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg);
65198 DUK_LOCAL_DECL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg);
65199 DUK_LOCAL_DECL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65200 DUK_LOCAL_DECL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65201 DUK_LOCAL_DECL
65202 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
65203                                           duk_ivalue *x,
65204                                           duk_regconst_t forced_reg,
65205                                           duk_small_uint_t flags);
65206 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65207 #if 0  /* unused */
65208 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65209 #endif
65210 DUK_LOCAL_DECL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg);
65211 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65212 DUK_LOCAL_DECL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x);
65213 
65214 /* identifier handling */
65215 DUK_LOCAL_DECL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx);
65216 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);
65217 
65218 /* label handling */
65219 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);
65220 DUK_LOCAL_DECL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags);
65221 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);
65222 DUK_LOCAL_DECL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len);
65223 
65224 /* top-down expression parser */
65225 DUK_LOCAL_DECL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65226 DUK_LOCAL_DECL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res);
65227 DUK_LOCAL_DECL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx);
65228 DUK_LOCAL_DECL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx);
65229 
65230 /* exprtop is the top level variant which resets nud/led counts */
65231 DUK_LOCAL_DECL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65232 DUK_LOCAL_DECL void duk__exprtop(duk_compiler_ctx *ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65233 
65234 /* convenience helpers */
65235 #if 0  /* unused */
65236 DUK_LOCAL_DECL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65237 #endif
65238 #if 0  /* unused */
65239 DUK_LOCAL_DECL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65240 #endif
65241 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);
65242 DUK_LOCAL_DECL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65243 #if 0  /* unused */
65244 DUK_LOCAL_DECL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65245 #endif
65246 DUK_LOCAL_DECL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65247 DUK_LOCAL_DECL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65248 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65249 #if 0  /* unused */
65250 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65251 #endif
65252 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);
65253 DUK_LOCAL_DECL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65254 #if 0  /* unused */
65255 DUK_LOCAL_DECL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags);
65256 #endif
65257 
65258 /* expression parsing helpers */
65259 DUK_LOCAL_DECL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65260 DUK_LOCAL_DECL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65261 DUK_LOCAL_DECL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65262 
65263 /* statement parsing */
65264 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);
65265 DUK_LOCAL_DECL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags);
65266 DUK_LOCAL_DECL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65267 DUK_LOCAL_DECL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65268 DUK_LOCAL_DECL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65269 DUK_LOCAL_DECL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65270 DUK_LOCAL_DECL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site);
65271 DUK_LOCAL_DECL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65272 DUK_LOCAL_DECL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65273 DUK_LOCAL_DECL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65274 DUK_LOCAL_DECL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65275 DUK_LOCAL_DECL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res);
65276 DUK_LOCAL_DECL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem);
65277 DUK_LOCAL_DECL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id);
65278 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);
65279 
65280 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);
65281 DUK_LOCAL_DECL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx);
65282 DUK_LOCAL_DECL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65283 DUK_LOCAL_DECL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags);
65284 
65285 #define DUK__FUNC_FLAG_DECL            (1 << 0)   /* Parsing a function declaration. */
65286 #define DUK__FUNC_FLAG_GETSET          (1 << 1)   /* Parsing an object literal getter/setter. */
65287 #define DUK__FUNC_FLAG_METDEF          (1 << 2)   /* Parsing an object literal method definition shorthand. */
65288 #define DUK__FUNC_FLAG_PUSHNAME_PASS1  (1 << 3)   /* Push function name when creating template (first pass only). */
65289 #define DUK__FUNC_FLAG_USE_PREVTOKEN   (1 << 4)   /* Use prev_token to start function parsing (workaround for object literal). */
65290 
65291 /*
65292  *  Parser control values for tokens.  The token table is ordered by the
65293  *  DUK_TOK_XXX defines.
65294  *
65295  *  The binding powers are for lbp() use (i.e. for use in led() context).
65296  *  Binding powers are positive for typing convenience, and bits at the
65297  *  top should be reserved for flags.  Binding power step must be higher
65298  *  than 1 so that binding power "lbp - 1" can be used for right associative
65299  *  operators.  Currently a step of 2 is used (which frees one more bit for
65300  *  flags).
65301  */
65302 
65303 /* XXX: actually single step levels would work just fine, clean up */
65304 
65305 /* binding power "levels" (see doc/compiler.rst) */
65306 #define DUK__BP_INVALID                0             /* always terminates led() */
65307 #define DUK__BP_EOF                    2
65308 #define DUK__BP_CLOSING                4             /* token closes expression, e.g. ')', ']' */
65309 #define DUK__BP_FOR_EXPR               DUK__BP_CLOSING    /* bp to use when parsing a top level Expression */
65310 #define DUK__BP_COMMA                  6
65311 #define DUK__BP_ASSIGNMENT             8
65312 #define DUK__BP_CONDITIONAL            10
65313 #define DUK__BP_LOR                    12
65314 #define DUK__BP_LAND                   14
65315 #define DUK__BP_BOR                    16
65316 #define DUK__BP_BXOR                   18
65317 #define DUK__BP_BAND                   20
65318 #define DUK__BP_EQUALITY               22
65319 #define DUK__BP_RELATIONAL             24
65320 #define DUK__BP_SHIFT                  26
65321 #define DUK__BP_ADDITIVE               28
65322 #define DUK__BP_MULTIPLICATIVE         30
65323 #define DUK__BP_EXPONENTIATION         32
65324 #define DUK__BP_POSTFIX                34
65325 #define DUK__BP_CALL                   36
65326 #define DUK__BP_MEMBER                 38
65327 
65328 #define DUK__TOKEN_LBP_BP_MASK         0x1f
65329 #define DUK__TOKEN_LBP_FLAG_NO_REGEXP  (1 << 5)   /* regexp literal must not follow this token */
65330 #define DUK__TOKEN_LBP_FLAG_TERMINATES (1 << 6)   /* terminates expression; e.g. post-increment/-decrement */
65331 #define DUK__TOKEN_LBP_FLAG_UNUSED     (1 << 7)   /* unused */
65332 
65333 #define DUK__TOKEN_LBP_GET_BP(x)       ((duk_small_uint_t) (((x) & DUK__TOKEN_LBP_BP_MASK) * 2))
65334 
65335 #define DUK__MK_LBP(bp)                ((bp) >> 1)    /* bp is assumed to be even */
65336 #define DUK__MK_LBP_FLAGS(bp,flags)    (((bp) >> 1) | (flags))
65337 
65338 DUK_LOCAL const duk_uint8_t duk__token_lbp[] = {
65339 	DUK__MK_LBP(DUK__BP_EOF),                                 /* DUK_TOK_EOF */
65340 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_IDENTIFIER */
65341 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BREAK */
65342 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CASE */
65343 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CATCH */
65344 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONTINUE */
65345 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEBUGGER */
65346 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DEFAULT */
65347 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DELETE */
65348 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_DO */
65349 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ELSE */
65350 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FINALLY */
65351 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FOR */
65352 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_FUNCTION */
65353 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IF */
65354 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_IN */
65355 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_INSTANCEOF */
65356 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_NEW */
65357 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_RETURN */
65358 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SWITCH */
65359 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_THIS */
65360 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_THROW */
65361 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TRY */
65362 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_TYPEOF */
65363 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VAR */
65364 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CONST */
65365 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_VOID */
65366 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WHILE */
65367 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_WITH */
65368 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_CLASS */
65369 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_ENUM */
65370 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXPORT */
65371 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_EXTENDS */
65372 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPORT */
65373 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SUPER */
65374 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NULL */
65375 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_TRUE */
65376 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_FALSE */
65377 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_GET */
65378 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SET */
65379 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_IMPLEMENTS */
65380 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_INTERFACE */
65381 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LET */
65382 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PACKAGE */
65383 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PRIVATE */
65384 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PROTECTED */
65385 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_PUBLIC */
65386 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_STATIC */
65387 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_YIELD */
65388 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LCURLY */
65389 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RCURLY */
65390 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_LBRACKET */
65391 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RBRACKET */
65392 	DUK__MK_LBP(DUK__BP_CALL),                                /* DUK_TOK_LPAREN */
65393 	DUK__MK_LBP_FLAGS(DUK__BP_CLOSING, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_RPAREN */
65394 	DUK__MK_LBP(DUK__BP_MEMBER),                              /* DUK_TOK_PERIOD */
65395 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_SEMICOLON */
65396 	DUK__MK_LBP(DUK__BP_COMMA),                               /* DUK_TOK_COMMA */
65397 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LT */
65398 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GT */
65399 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_LE */
65400 	DUK__MK_LBP(DUK__BP_RELATIONAL),                          /* DUK_TOK_GE */
65401 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_EQ */
65402 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_NEQ */
65403 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SEQ */
65404 	DUK__MK_LBP(DUK__BP_EQUALITY),                            /* DUK_TOK_SNEQ */
65405 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_ADD */
65406 	DUK__MK_LBP(DUK__BP_ADDITIVE),                            /* DUK_TOK_SUB */
65407 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MUL */
65408 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_DIV */
65409 	DUK__MK_LBP(DUK__BP_MULTIPLICATIVE),                      /* DUK_TOK_MOD */
65410 	DUK__MK_LBP(DUK__BP_EXPONENTIATION),                      /* DUK_TOK_EXP */
65411 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_INCREMENT */
65412 	DUK__MK_LBP(DUK__BP_POSTFIX),                             /* DUK_TOK_DECREMENT */
65413 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ALSHIFT */
65414 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_ARSHIFT */
65415 	DUK__MK_LBP(DUK__BP_SHIFT),                               /* DUK_TOK_RSHIFT */
65416 	DUK__MK_LBP(DUK__BP_BAND),                                /* DUK_TOK_BAND */
65417 	DUK__MK_LBP(DUK__BP_BOR),                                 /* DUK_TOK_BOR */
65418 	DUK__MK_LBP(DUK__BP_BXOR),                                /* DUK_TOK_BXOR */
65419 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_LNOT */
65420 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_BNOT */
65421 	DUK__MK_LBP(DUK__BP_LAND),                                /* DUK_TOK_LAND */
65422 	DUK__MK_LBP(DUK__BP_LOR),                                 /* DUK_TOK_LOR */
65423 	DUK__MK_LBP(DUK__BP_CONDITIONAL),                         /* DUK_TOK_QUESTION */
65424 	DUK__MK_LBP(DUK__BP_INVALID),                             /* DUK_TOK_COLON */
65425 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EQUALSIGN */
65426 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ADD_EQ */
65427 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_SUB_EQ */
65428 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MUL_EQ */
65429 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_DIV_EQ */
65430 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_MOD_EQ */
65431 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_EXP_EQ */
65432 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ALSHIFT_EQ */
65433 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_ARSHIFT_EQ */
65434 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_RSHIFT_EQ */
65435 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BAND_EQ */
65436 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BOR_EQ */
65437 	DUK__MK_LBP(DUK__BP_ASSIGNMENT),                          /* DUK_TOK_BXOR_EQ */
65438 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_NUMBER */
65439 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_STRING */
65440 	DUK__MK_LBP_FLAGS(DUK__BP_INVALID, DUK__TOKEN_LBP_FLAG_NO_REGEXP),  /* DUK_TOK_REGEXP */
65441 };
65442 
65443 /*
65444  *  Misc helpers
65445  */
65446 
65447 DUK_LOCAL void duk__comp_recursion_increase(duk_compiler_ctx *comp_ctx) {
65448 	DUK_ASSERT(comp_ctx != NULL);
65449 	DUK_ASSERT(comp_ctx->recursion_depth >= 0);
65450 	if (comp_ctx->recursion_depth >= comp_ctx->recursion_limit) {
65451 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_COMPILER_RECURSION_LIMIT);
65452 		DUK_WO_NORETURN(return;);
65453 	}
65454 	comp_ctx->recursion_depth++;
65455 }
65456 
65457 DUK_LOCAL void duk__comp_recursion_decrease(duk_compiler_ctx *comp_ctx) {
65458 	DUK_ASSERT(comp_ctx != NULL);
65459 	DUK_ASSERT(comp_ctx->recursion_depth > 0);
65460 	comp_ctx->recursion_depth--;
65461 }
65462 
65463 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
65464 	DUK_UNREF(comp_ctx);
65465 	DUK_ASSERT(h != NULL);
65466 	return DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h);
65467 }
65468 
65469 DUK_LOCAL duk_bool_t duk__hstring_is_eval_or_arguments_in_strict_mode(duk_compiler_ctx *comp_ctx, duk_hstring *h) {
65470 	DUK_ASSERT(h != NULL);
65471 	return (comp_ctx->curr_func.is_strict &&
65472 	        DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(h));
65473 }
65474 
65475 /*
65476  *  Parser duk__advance() token eating functions
65477  */
65478 
65479 /* XXX: valstack handling is awkward.  Add a valstack helper which
65480  * avoids dup():ing; valstack_copy(src, dst)?
65481  */
65482 
65483 DUK_LOCAL void duk__advance_helper(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
65484 	duk_hthread *thr = comp_ctx->thr;
65485 	duk_bool_t regexp;
65486 
65487 	DUK_ASSERT_DISABLE(comp_ctx->curr_token.t >= 0);  /* unsigned */
65488 	DUK_ASSERT(comp_ctx->curr_token.t <= DUK_TOK_MAXVAL);  /* MAXVAL is inclusive */
65489 
65490 	/*
65491 	 *  Use current token to decide whether a RegExp can follow.
65492 	 *
65493 	 *  We can use either 't' or 't_nores'; the latter would not
65494 	 *  recognize keywords.  Some keywords can be followed by a
65495 	 *  RegExp (e.g. "return"), so using 't' is better.  This is
65496 	 *  not trivial, see doc/compiler.rst.
65497 	 */
65498 
65499 	regexp = 1;
65500 	if (duk__token_lbp[comp_ctx->curr_token.t] & DUK__TOKEN_LBP_FLAG_NO_REGEXP) {
65501 		regexp = 0;
65502 	}
65503 	if (comp_ctx->curr_func.reject_regexp_in_adv) {
65504 		comp_ctx->curr_func.reject_regexp_in_adv = 0;
65505 		regexp = 0;
65506 	}
65507 	if (comp_ctx->curr_func.allow_regexp_in_adv) {
65508 		comp_ctx->curr_func.allow_regexp_in_adv = 0;
65509 		regexp = 1;
65510 	}
65511 
65512 	if (expect >= 0 && comp_ctx->curr_token.t != (duk_small_uint_t) expect) {
65513 		DUK_D(DUK_DPRINT("parse error: expect=%ld, got=%ld",
65514 		                 (long) expect, (long) comp_ctx->curr_token.t));
65515 		DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
65516 		DUK_WO_NORETURN(return;);
65517 	}
65518 
65519 	/* make current token the previous; need to fiddle with valstack "backing store" */
65520 	duk_memcpy(&comp_ctx->prev_token, &comp_ctx->curr_token, sizeof(duk_token));
65521 	duk_copy(thr, comp_ctx->tok11_idx, comp_ctx->tok21_idx);
65522 	duk_copy(thr, comp_ctx->tok12_idx, comp_ctx->tok22_idx);
65523 
65524 	/* parse new token */
65525 	duk_lexer_parse_js_input_element(&comp_ctx->lex,
65526 	                                 &comp_ctx->curr_token,
65527 	                                 comp_ctx->curr_func.is_strict,
65528 	                                 regexp);
65529 
65530 	DUK_DDD(DUK_DDDPRINT("advance: curr: tok=%ld/%ld,%ld,term=%ld,%!T,%!T "
65531 	                     "prev: tok=%ld/%ld,%ld,term=%ld,%!T,%!T",
65532 	                     (long) comp_ctx->curr_token.t,
65533 	                     (long) comp_ctx->curr_token.t_nores,
65534 	                     (long) comp_ctx->curr_token.start_line,
65535 	                     (long) comp_ctx->curr_token.lineterm,
65536 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok11_idx),
65537 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok12_idx),
65538 	                     (long) comp_ctx->prev_token.t,
65539 	                     (long) comp_ctx->prev_token.t_nores,
65540 	                     (long) comp_ctx->prev_token.start_line,
65541 	                     (long) comp_ctx->prev_token.lineterm,
65542 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok21_idx),
65543 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->tok22_idx)));
65544 }
65545 
65546 /* advance, expecting current token to be a specific token; parse next token in regexp context */
65547 DUK_LOCAL void duk__advance_expect(duk_compiler_ctx *comp_ctx, duk_small_int_t expect) {
65548 	duk__advance_helper(comp_ctx, expect);
65549 }
65550 
65551 /* advance, whatever the current token is; parse next token in regexp context */
65552 DUK_LOCAL void duk__advance(duk_compiler_ctx *comp_ctx) {
65553 	duk__advance_helper(comp_ctx, -1);
65554 }
65555 
65556 /*
65557  *  Helpers for duk_compiler_func.
65558  */
65559 
65560 /* init function state: inits valstack allocations */
65561 DUK_LOCAL void duk__init_func_valstack_slots(duk_compiler_ctx *comp_ctx) {
65562 	duk_compiler_func *func = &comp_ctx->curr_func;
65563 	duk_hthread *thr = comp_ctx->thr;
65564 	duk_idx_t entry_top;
65565 
65566 	entry_top = duk_get_top(thr);
65567 
65568 	duk_memzero(func, sizeof(*func));  /* intentional overlap with earlier memzero */
65569 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
65570 	func->h_name = NULL;
65571 	func->h_consts = NULL;
65572 	func->h_funcs = NULL;
65573 	func->h_decls = NULL;
65574 	func->h_labelnames = NULL;
65575 	func->h_labelinfos = NULL;
65576 	func->h_argnames = NULL;
65577 	func->h_varmap = NULL;
65578 #endif
65579 
65580 	duk_require_stack(thr, DUK__FUNCTION_INIT_REQUIRE_SLOTS);
65581 
65582 	DUK_BW_INIT_PUSHBUF(thr, &func->bw_code, DUK__BC_INITIAL_INSTS * sizeof(duk_compiler_instr));
65583 	/* code_idx = entry_top + 0 */
65584 
65585 	duk_push_array(thr);
65586 	func->consts_idx = entry_top + 1;
65587 	func->h_consts = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 1);
65588 	DUK_ASSERT(func->h_consts != NULL);
65589 
65590 	duk_push_array(thr);
65591 	func->funcs_idx = entry_top + 2;
65592 	func->h_funcs = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 2);
65593 	DUK_ASSERT(func->h_funcs != NULL);
65594 	DUK_ASSERT(func->fnum_next == 0);
65595 
65596 	duk_push_array(thr);
65597 	func->decls_idx = entry_top + 3;
65598 	func->h_decls = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 3);
65599 	DUK_ASSERT(func->h_decls != NULL);
65600 
65601 	duk_push_array(thr);
65602 	func->labelnames_idx = entry_top + 4;
65603 	func->h_labelnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 4);
65604 	DUK_ASSERT(func->h_labelnames != NULL);
65605 
65606 	duk_push_dynamic_buffer(thr, 0);
65607 	func->labelinfos_idx = entry_top + 5;
65608 	func->h_labelinfos = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 5);
65609 	DUK_ASSERT(func->h_labelinfos != NULL);
65610 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(func->h_labelinfos) && !DUK_HBUFFER_HAS_EXTERNAL(func->h_labelinfos));
65611 
65612 	duk_push_array(thr);
65613 	func->argnames_idx = entry_top + 6;
65614 	func->h_argnames = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 6);
65615 	DUK_ASSERT(func->h_argnames != NULL);
65616 
65617 	duk_push_bare_object(thr);
65618 	func->varmap_idx = entry_top + 7;
65619 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, entry_top + 7);
65620 	DUK_ASSERT(func->h_varmap != NULL);
65621 }
65622 
65623 /* reset function state (prepare for pass 2) */
65624 DUK_LOCAL void duk__reset_func_for_pass2(duk_compiler_ctx *comp_ctx) {
65625 	duk_compiler_func *func = &comp_ctx->curr_func;
65626 	duk_hthread *thr = comp_ctx->thr;
65627 
65628 	/* reset bytecode buffer but keep current size; pass 2 will
65629 	 * require same amount or more.
65630 	 */
65631 	DUK_BW_RESET_SIZE(thr, &func->bw_code);
65632 
65633 	duk_set_length(thr, func->consts_idx, 0);
65634 	/* keep func->h_funcs; inner functions are not reparsed to avoid O(depth^2) parsing */
65635 	func->fnum_next = 0;
65636 	/* duk_set_length(thr, func->funcs_idx, 0); */
65637 	duk_set_length(thr, func->labelnames_idx, 0);
65638 	duk_hbuffer_reset(thr, func->h_labelinfos);
65639 	/* keep func->h_argnames; it is fixed for all passes */
65640 
65641 	/* truncated in case pass 3 needed */
65642 	duk_push_bare_object(thr);
65643 	duk_replace(thr, func->varmap_idx);
65644 	func->h_varmap = DUK_GET_HOBJECT_POSIDX(thr, func->varmap_idx);
65645 	DUK_ASSERT(func->h_varmap != NULL);
65646 }
65647 
65648 /* cleanup varmap from any null entries, compact it, etc; returns number
65649  * of final entries after cleanup.
65650  */
65651 DUK_LOCAL duk_int_t duk__cleanup_varmap(duk_compiler_ctx *comp_ctx) {
65652 	duk_hthread *thr = comp_ctx->thr;
65653 	duk_hobject *h_varmap;
65654 	duk_hstring *h_key;
65655 	duk_tval *tv;
65656 	duk_uint32_t i, e_next;
65657 	duk_int_t ret;
65658 
65659 	/* [ ... varmap ] */
65660 
65661 	h_varmap = DUK_GET_HOBJECT_NEGIDX(thr, -1);
65662 	DUK_ASSERT(h_varmap != NULL);
65663 
65664 	ret = 0;
65665 	e_next = DUK_HOBJECT_GET_ENEXT(h_varmap);
65666 	for (i = 0; i < e_next; i++) {
65667 		h_key = DUK_HOBJECT_E_GET_KEY(thr->heap, h_varmap, i);
65668 		if (!h_key) {
65669 			continue;
65670 		}
65671 
65672 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, h_varmap, i));
65673 
65674 		/* The entries can either be register numbers or 'null' values.
65675 		 * Thus, no need to DECREF them and get side effects.  DECREF'ing
65676 		 * the keys (strings) can cause memory to be freed but no side
65677 		 * effects as strings don't have finalizers.  This is why we can
65678 		 * rely on the object properties not changing from underneath us.
65679 		 */
65680 
65681 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, h_varmap, i);
65682 		if (!DUK_TVAL_IS_NUMBER(tv)) {
65683 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));
65684 			DUK_HOBJECT_E_SET_KEY(thr->heap, h_varmap, i, NULL);
65685 			DUK_HSTRING_DECREF(thr, h_key);
65686 			/* when key is NULL, value is garbage so no need to set */
65687 		} else {
65688 			ret++;
65689 		}
65690 	}
65691 
65692 	duk_compact_m1(thr);
65693 
65694 	return ret;
65695 }
65696 
65697 /* Convert duk_compiler_func into a function template, leaving the result
65698  * on top of stack.
65699  */
65700 /* XXX: awkward and bloated asm -- use faster internal accesses */
65701 DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx) {
65702 	duk_compiler_func *func = &comp_ctx->curr_func;
65703 	duk_hthread *thr = comp_ctx->thr;
65704 	duk_hcompfunc *h_res;
65705 	duk_hbuffer_fixed *h_data;
65706 	duk_size_t consts_count;
65707 	duk_size_t funcs_count;
65708 	duk_size_t code_count;
65709 	duk_size_t code_size;
65710 	duk_size_t data_size;
65711 	duk_size_t i;
65712 	duk_tval *p_const;
65713 	duk_hobject **p_func;
65714 	duk_instr_t *p_instr;
65715 	duk_compiler_instr *q_instr;
65716 	duk_tval *tv;
65717 	duk_bool_t keep_varmap;
65718 	duk_bool_t keep_formals;
65719 #if !defined(DUK_USE_DEBUGGER_SUPPORT)
65720 	duk_size_t formals_length;
65721 #endif
65722 
65723 	DUK_DDD(DUK_DDDPRINT("converting duk_compiler_func to function/template"));
65724 
65725 	/*
65726 	 *  Push result object and init its flags
65727 	 */
65728 
65729 	/* Valstack should suffice here, required on function valstack init */
65730 
65731 	h_res = duk_push_hcompfunc(thr);
65732 	DUK_ASSERT(h_res != NULL);
65733 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) h_res) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
65734 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, (duk_hobject *) h_res, NULL);  /* Function templates are "bare objects". */
65735 
65736 	if (func->is_function) {
65737 		DUK_DDD(DUK_DDDPRINT("function -> set NEWENV"));
65738 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
65739 
65740 		if (!func->is_arguments_shadowed) {
65741 			/* arguments object would be accessible; note that shadowing
65742 			 * bindings are arguments or function declarations, neither
65743 			 * of which are deletable, so this is safe.
65744 			 */
65745 
65746 			if (func->id_access_arguments || func->may_direct_eval) {
65747 				DUK_DDD(DUK_DDDPRINT("function may access 'arguments' object directly or "
65748 				                     "indirectly -> set CREATEARGS"));
65749 				DUK_HOBJECT_SET_CREATEARGS((duk_hobject *) h_res);
65750 			}
65751 		}
65752 	} else if (func->is_eval && func->is_strict) {
65753 		DUK_DDD(DUK_DDDPRINT("strict eval code -> set NEWENV"));
65754 		DUK_HOBJECT_SET_NEWENV((duk_hobject *) h_res);
65755 	} else {
65756 		/* non-strict eval: env is caller's env or global env (direct vs. indirect call)
65757 		 * global code: env is is global env
65758 		 */
65759 		DUK_DDD(DUK_DDDPRINT("non-strict eval code or global code -> no NEWENV"));
65760 		DUK_ASSERT(!DUK_HOBJECT_HAS_NEWENV((duk_hobject *) h_res));
65761 	}
65762 
65763 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
65764 	if (func->is_function && func->is_namebinding && func->h_name != NULL) {
65765 		/* Object literal set/get functions have a name (property
65766 		 * name) but must not have a lexical name binding, see
65767 		 * test-bug-getset-func-name.js.
65768 		 */
65769 		DUK_DDD(DUK_DDDPRINT("function expression with a name -> set NAMEBINDING"));
65770 		DUK_HOBJECT_SET_NAMEBINDING((duk_hobject *) h_res);
65771 	}
65772 #endif
65773 
65774 	if (func->is_strict) {
65775 		DUK_DDD(DUK_DDDPRINT("function is strict -> set STRICT"));
65776 		DUK_HOBJECT_SET_STRICT((duk_hobject *) h_res);
65777 	}
65778 
65779 	if (func->is_notail) {
65780 		DUK_DDD(DUK_DDDPRINT("function is notail -> set NOTAIL"));
65781 		DUK_HOBJECT_SET_NOTAIL((duk_hobject *) h_res);
65782 	}
65783 
65784 	if (func->is_constructable) {
65785 		DUK_DDD(DUK_DDDPRINT("function is constructable -> set CONSTRUCTABLE"));
65786 		DUK_HOBJECT_SET_CONSTRUCTABLE((duk_hobject *) h_res);
65787 	}
65788 
65789 	/*
65790 	 *  Build function fixed size 'data' buffer, which contains bytecode,
65791 	 *  constants, and inner function references.
65792 	 *
65793 	 *  During the building phase 'data' is reachable but incomplete.
65794 	 *  Only incref's occur during building (no refzero or GC happens),
65795 	 *  so the building process is atomic.
65796 	 */
65797 
65798 	consts_count = duk_hobject_get_length(thr, func->h_consts);
65799 	funcs_count = duk_hobject_get_length(thr, func->h_funcs) / 3;
65800 	code_count = DUK_BW_GET_SIZE(thr, &func->bw_code) / sizeof(duk_compiler_instr);
65801 	code_size = code_count * sizeof(duk_instr_t);
65802 
65803 	data_size = consts_count * sizeof(duk_tval) +
65804 	            funcs_count * sizeof(duk_hobject *) +
65805 	            code_size;
65806 
65807 	DUK_DDD(DUK_DDDPRINT("consts_count=%ld, funcs_count=%ld, code_size=%ld -> "
65808 	                     "data_size=%ld*%ld + %ld*%ld + %ld = %ld",
65809 	                     (long) consts_count, (long) funcs_count, (long) code_size,
65810 	                     (long) consts_count, (long) sizeof(duk_tval),
65811 	                     (long) funcs_count, (long) sizeof(duk_hobject *),
65812 	                     (long) code_size, (long) data_size));
65813 
65814 	duk_push_fixed_buffer_nozero(thr, data_size);
65815 	h_data = (duk_hbuffer_fixed *) (void *) duk_known_hbuffer(thr, -1);
65816 
65817 	DUK_HCOMPFUNC_SET_DATA(thr->heap, h_res, (duk_hbuffer *) h_data);
65818 	DUK_HEAPHDR_INCREF(thr, h_data);
65819 
65820 	p_const = (duk_tval *) (void *) DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data);
65821 	for (i = 0; i < consts_count; i++) {
65822 		DUK_ASSERT(i <= DUK_UARRIDX_MAX);  /* const limits */
65823 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_consts, (duk_uarridx_t) i);
65824 		DUK_ASSERT(tv != NULL);
65825 		DUK_TVAL_SET_TVAL(p_const, tv);
65826 		p_const++;
65827 		DUK_TVAL_INCREF(thr, tv);  /* may be a string constant */
65828 
65829 		DUK_DDD(DUK_DDDPRINT("constant: %!T", (duk_tval *) tv));
65830 	}
65831 
65832 	p_func = (duk_hobject **) p_const;
65833 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, h_res, p_func);
65834 	for (i = 0; i < funcs_count; i++) {
65835 		duk_hobject *h;
65836 		DUK_ASSERT(i * 3 <= DUK_UARRIDX_MAX);  /* func limits */
65837 		tv = duk_hobject_find_existing_array_entry_tval_ptr(thr->heap, func->h_funcs, (duk_uarridx_t) (i * 3));
65838 		DUK_ASSERT(tv != NULL);
65839 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
65840 		h = DUK_TVAL_GET_OBJECT(tv);
65841 		DUK_ASSERT(h != NULL);
65842 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(h));
65843 		*p_func++ = h;
65844 		DUK_HOBJECT_INCREF(thr, h);
65845 
65846 		DUK_DDD(DUK_DDDPRINT("inner function: %p -> %!iO",
65847 		                     (void *) h, (duk_heaphdr *) h));
65848 	}
65849 
65850 	p_instr = (duk_instr_t *) p_func;
65851 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, h_res, p_instr);
65852 
65853 	/* copy bytecode instructions one at a time */
65854 	q_instr = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(thr, &func->bw_code);
65855 	for (i = 0; i < code_count; i++) {
65856 		p_instr[i] = q_instr[i].ins;
65857 	}
65858 	/* Note: 'q_instr' is still used below */
65859 
65860 	DUK_ASSERT((duk_uint8_t *) (p_instr + code_count) == DUK_HBUFFER_FIXED_GET_DATA_PTR(thr->heap, h_data) + data_size);
65861 
65862 	duk_pop(thr);  /* 'data' (and everything in it) is reachable through h_res now */
65863 
65864 	/*
65865 	 *  Init non-property result fields
65866 	 *
65867 	 *  'nregs' controls how large a register frame is allocated.
65868 	 *
65869 	 *  'nargs' controls how many formal arguments are written to registers:
65870 	 *  r0, ... r(nargs-1).  The remaining registers are initialized to
65871 	 *  undefined.
65872 	 */
65873 
65874 	DUK_ASSERT(func->temp_max >= 0);
65875 	h_res->nregs = (duk_uint16_t) func->temp_max;
65876 	h_res->nargs = (duk_uint16_t) duk_hobject_get_length(thr, func->h_argnames);
65877 	DUK_ASSERT(h_res->nregs >= h_res->nargs);  /* pass2 allocation handles this */
65878 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65879 	h_res->start_line = (duk_uint32_t) func->min_line;
65880 	h_res->end_line = (duk_uint32_t) func->max_line;
65881 #endif
65882 
65883 	/*
65884 	 *  Init object properties
65885 	 *
65886 	 *  Properties should be added in decreasing order of access frequency.
65887 	 *  (Not very critical for function templates.)
65888 	 */
65889 
65890 	DUK_DDD(DUK_DDDPRINT("init function properties"));
65891 
65892 	/* [ ... res ] */
65893 
65894 	/* _Varmap: omitted if function is guaranteed not to do a slow path
65895 	 * identifier access that might be caught by locally declared variables.
65896 	 * The varmap can also be omitted if it turns out empty of actual
65897 	 * register mappings after a cleanup.  When debugging is enabled, we
65898 	 * always need the varmap to be able to lookup variables at any point.
65899 	 */
65900 
65901 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65902 	DUK_DD(DUK_DDPRINT("keeping _Varmap because debugger support is enabled"));
65903 	keep_varmap = 1;
65904 #else
65905 	if (func->id_access_slow_own ||   /* directly uses slow accesses that may match own variables */
65906 	    func->id_access_arguments ||  /* accesses 'arguments' directly */
65907 	    func->may_direct_eval ||      /* may indirectly slow access through a direct eval */
65908 	    funcs_count > 0) {            /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
65909 		DUK_DD(DUK_DDPRINT("keeping _Varmap because of direct eval, slow path access that may match local variables, or presence of inner functions"));
65910 		keep_varmap = 1;
65911 	} else {
65912 		DUK_DD(DUK_DDPRINT("dropping _Varmap"));
65913 		keep_varmap = 0;
65914 	}
65915 #endif
65916 
65917 	if (keep_varmap) {
65918 		duk_int_t num_used;
65919 		duk_dup(thr, func->varmap_idx);
65920 		num_used = duk__cleanup_varmap(comp_ctx);
65921 		DUK_DDD(DUK_DDDPRINT("cleaned up varmap: %!T (num_used=%ld)",
65922 		                     (duk_tval *) duk_get_tval(thr, -1), (long) num_used));
65923 
65924 		if (num_used > 0) {
65925 			duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_VARMAP, DUK_PROPDESC_FLAGS_NONE);
65926 		} else {
65927 			DUK_DD(DUK_DDPRINT("varmap is empty after cleanup -> no need to add"));
65928 			duk_pop(thr);
65929 		}
65930 	}
65931 
65932 	/* _Formals: omitted if function is guaranteed not to need a (non-strict)
65933 	 * arguments object, and _Formals.length matches nargs exactly.
65934 	 *
65935 	 * Non-arrow functions can't see an outer function's 'argument' binding
65936 	 * (because they have their own), but arrow functions can.  When arrow
65937 	 * functions are added, this condition would need to be added:
65938 	 *     inner_arrow_funcs_count > 0   inner arrow functions may access 'arguments'
65939 	 */
65940 #if defined(DUK_USE_DEBUGGER_SUPPORT)
65941 	DUK_DD(DUK_DDPRINT("keeping _Formals because debugger support is enabled"));
65942 	keep_formals = 1;
65943 #else
65944 	formals_length = duk_get_length(thr, func->argnames_idx);
65945 	if (formals_length != (duk_size_t) h_res->nargs) {
65946 		/* Nargs not enough for closure .length: keep _Formals regardless
65947 		 * of its length.  Shouldn't happen in practice at the moment.
65948 		 */
65949 		DUK_DD(DUK_DDPRINT("keeping _Formals because _Formals.length != nargs"));
65950 		keep_formals = 1;
65951 	} else if ((func->id_access_arguments || func->may_direct_eval) &&
65952 	           (formals_length > 0)) {
65953 		/* Direct eval (may access 'arguments') or accesses 'arguments'
65954 		 * explicitly: keep _Formals unless it is zero length.
65955 		 */
65956 		DUK_DD(DUK_DDPRINT("keeping _Formals because of direct eval or explicit access to 'arguments', and _Formals.length != 0"));
65957 		keep_formals = 1;
65958 	} else {
65959 		DUK_DD(DUK_DDPRINT("omitting _Formals, nargs matches _Formals.length, so no properties added"));
65960 		keep_formals = 0;
65961 	}
65962 #endif
65963 
65964 	if (keep_formals) {
65965 		duk_dup(thr, func->argnames_idx);
65966 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_FORMALS, DUK_PROPDESC_FLAGS_NONE);
65967 	}
65968 
65969 	/* name */
65970 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
65971 	if (func->h_name) {
65972 		duk_push_hstring(thr, func->h_name);
65973 		DUK_DD(DUK_DDPRINT("setting function template .name to %!T", duk_get_tval(thr, -1)));
65974 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_NONE);
65975 	}
65976 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
65977 
65978 	/* _Source */
65979 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
65980 	if (0) {
65981 		/* XXX: Currently function source code is not stored, as it is not
65982 		 * required by the standard.  Source code should not be stored by
65983 		 * default (user should enable it explicitly), and the source should
65984 		 * probably be compressed with a trivial text compressor; average
65985 		 * compression of 20-30% is quite easy to achieve even with a trivial
65986 		 * compressor (RLE + backwards lookup).
65987 		 *
65988 		 * Debugging needs source code to be useful: sometimes input code is
65989 		 * not found in files as it may be generated and then eval()'d, given
65990 		 * by dynamic C code, etc.
65991 		 *
65992 		 * Other issues:
65993 		 *
65994 		 *   - Need tokenizer indices for start and end to substring
65995 		 *   - Always normalize function declaration part?
65996 		 *   - If we keep _Formals, only need to store body
65997 		 */
65998 
65999 		/*
66000 		 *  For global or eval code this is straightforward.  For functions
66001 		 *  created with the Function constructor we only get the source for
66002 		 *  the body and must manufacture the "function ..." part.
66003 		 *
66004 		 *  For instance, for constructed functions (v8):
66005 		 *
66006 		 *    > a = new Function("foo", "bar", "print(foo)");
66007 		 *    [Function]
66008 		 *    > a.toString()
66009 		 *    'function anonymous(foo,bar) {\nprint(foo)\n}'
66010 		 *
66011 		 *  Similarly for e.g. getters (v8):
66012 		 *
66013 		 *    > x = { get a(foo,bar) { print(foo); } }
66014 		 *    { a: [Getter] }
66015 		 *    > Object.getOwnPropertyDescriptor(x, 'a').get.toString()
66016 		 *    'function a(foo,bar) { print(foo); }'
66017 		 */
66018 
66019 #if 0
66020 		duk_push_literal(thr, "XXX");
66021 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
66022 #endif
66023 	}
66024 #endif  /* DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY */
66025 
66026 	/* _Pc2line */
66027 #if defined(DUK_USE_PC2LINE)
66028 	if (1) {
66029 		/*
66030 		 *  Size-optimized pc->line mapping.
66031 		 */
66032 
66033 		DUK_ASSERT(code_count <= DUK_COMPILER_MAX_BYTECODE_LENGTH);
66034 		duk_hobject_pc2line_pack(thr, q_instr, (duk_uint_fast32_t) code_count);  /* -> pushes fixed buffer */
66035 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_PC2LINE, DUK_PROPDESC_FLAGS_NONE);
66036 
66037 		/* XXX: if assertions enabled, walk through all valid PCs
66038 		 * and check line mapping.
66039 		 */
66040 	}
66041 #endif  /* DUK_USE_PC2LINE */
66042 
66043 	/* fileName */
66044 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
66045 	if (comp_ctx->h_filename) {
66046 		/*
66047 		 *  Source filename (or equivalent), for identifying thrown errors.
66048 		 */
66049 
66050 		duk_push_hstring(thr, comp_ctx->h_filename);
66051 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_FILE_NAME, DUK_PROPDESC_FLAGS_NONE);
66052 	}
66053 #endif
66054 
66055 	DUK_DD(DUK_DDPRINT("converted function: %!ixT",
66056 	                   (duk_tval *) duk_get_tval(thr, -1)));
66057 
66058 	/*
66059 	 *  Compact the function template.
66060 	 */
66061 
66062 	duk_compact_m1(thr);
66063 
66064 	/*
66065 	 *  Debug dumping
66066 	 */
66067 
66068 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
66069 	{
66070 		duk_hcompfunc *h;
66071 		duk_instr_t *p, *p_start, *p_end;
66072 
66073 		h = (duk_hcompfunc *) duk_get_hobject(thr, -1);
66074 		p_start = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, h);
66075 		p_end = (duk_instr_t *) DUK_HCOMPFUNC_GET_CODE_END(thr->heap, h);
66076 
66077 		p = p_start;
66078 		while (p < p_end) {
66079 			DUK_DDD(DUK_DDDPRINT("BC %04ld: %!I        ; 0x%08lx op=%ld (%!C) a=%ld b=%ld c=%ld",
66080 			                     (long) (p - p_start),
66081 			                     (duk_instr_t) (*p),
66082 			                     (unsigned long) (*p),
66083 			                     (long) DUK_DEC_OP(*p),
66084 			                     (long) DUK_DEC_OP(*p),
66085 			                     (long) DUK_DEC_A(*p),
66086 			                     (long) DUK_DEC_B(*p),
66087 			                     (long) DUK_DEC_C(*p)));
66088 			p++;
66089 		}
66090 	}
66091 #endif
66092 }
66093 
66094 /*
66095  *  Code emission helpers
66096  *
66097  *  Some emission helpers understand the range of target and source reg/const
66098  *  values and automatically emit shuffling code if necessary.  This is the
66099  *  case when the slot in question (A, B, C) is used in the standard way and
66100  *  for opcodes the emission helpers explicitly understand (like DUK_OP_MPUTOBJ).
66101  *
66102  *  The standard way is that:
66103  *    - slot A is a target register
66104  *    - slot B is a source register/constant
66105  *    - slot C is a source register/constant
66106  *
66107  *  If a slot is used in a non-standard way the caller must indicate this
66108  *  somehow.  If a slot is used as a target instead of a source (or vice
66109  *  versa), this can be indicated with a flag to trigger proper shuffling
66110  *  (e.g. DUK__EMIT_FLAG_B_IS_TARGET).  If the value in the slot is not
66111  *  register/const related at all, the caller must ensure that the raw value
66112  *  fits into the corresponding slot so as to not trigger shuffling.  The
66113  *  caller must set a "no shuffle" flag to ensure compilation fails if
66114  *  shuffling were to be triggered because of an internal error.
66115  *
66116  *  For slots B and C the raw slot size is 9 bits but one bit is reserved for
66117  *  the reg/const indicator.  To use the full 9-bit range for a raw value,
66118  *  shuffling must be disabled with the DUK__EMIT_FLAG_NO_SHUFFLE_{B,C} flag.
66119  *  Shuffling is only done for A, B, and C slots, not the larger BC or ABC slots.
66120  *
66121  *  There is call handling specific understanding in the A-B-C emitter to
66122  *  convert call setup and call instructions into indirect ones if necessary.
66123  */
66124 
66125 /* Code emission flags, passed in the 'opcode' field.  Opcode + flags
66126  * fit into 16 bits for now, so use duk_small_uint_t.
66127  */
66128 #define DUK__EMIT_FLAG_NO_SHUFFLE_A      (1 << 8)
66129 #define DUK__EMIT_FLAG_NO_SHUFFLE_B      (1 << 9)
66130 #define DUK__EMIT_FLAG_NO_SHUFFLE_C      (1 << 10)
66131 #define DUK__EMIT_FLAG_A_IS_SOURCE       (1 << 11)  /* slot A is a source (default: target) */
66132 #define DUK__EMIT_FLAG_B_IS_TARGET       (1 << 12)  /* slot B is a target (default: source) */
66133 #define DUK__EMIT_FLAG_C_IS_TARGET       (1 << 13)  /* slot C is a target (default: source) */
66134 #define DUK__EMIT_FLAG_BC_REGCONST       (1 << 14)  /* slots B and C are reg/const */
66135 #define DUK__EMIT_FLAG_RESERVE_JUMPSLOT  (1 << 15)  /* reserve a jumpslot after instr before target spilling, used for NEXTENUM */
66136 
66137 /* XXX: macro smaller than call? */
66138 DUK_LOCAL duk_int_t duk__get_current_pc(duk_compiler_ctx *comp_ctx) {
66139 	duk_compiler_func *func;
66140 	func = &comp_ctx->curr_func;
66141 	return (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &func->bw_code) / sizeof(duk_compiler_instr));
66142 }
66143 
66144 DUK_LOCAL duk_compiler_instr *duk__get_instr_ptr(duk_compiler_ctx *comp_ctx, duk_int_t pc) {
66145 	DUK_ASSERT(pc >= 0);
66146 	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)));
66147 	return ((duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code)) + pc;
66148 }
66149 
66150 /* emit instruction; could return PC but that's not needed in the majority
66151  * of cases.
66152  */
66153 DUK_LOCAL void duk__emit(duk_compiler_ctx *comp_ctx, duk_instr_t ins) {
66154 #if defined(DUK_USE_PC2LINE)
66155 	duk_int_t line;
66156 #endif
66157 	duk_compiler_instr *instr;
66158 
66159 	DUK_DDD(DUK_DDDPRINT("duk__emit: 0x%08lx curr_token.start_line=%ld prev_token.start_line=%ld pc=%ld --> %!I",
66160 	                     (unsigned long) ins,
66161 	                     (long) comp_ctx->curr_token.start_line,
66162 	                     (long) comp_ctx->prev_token.start_line,
66163 	                     (long) duk__get_current_pc(comp_ctx),
66164 	                     (duk_instr_t) ins));
66165 
66166 	instr = (duk_compiler_instr *) (void *) DUK_BW_ENSURE_GETPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66167 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66168 
66169 #if defined(DUK_USE_PC2LINE)
66170 	/* The line number tracking is a bit inconsistent right now, which
66171 	 * affects debugger accuracy.  Mostly call sites emit opcodes when
66172 	 * they have parsed a token (say a terminating semicolon) and called
66173 	 * duk__advance().  In this case the line number of the previous
66174 	 * token is the most accurate one (except in prologue where
66175 	 * prev_token.start_line is 0).  This is probably not 100% correct
66176 	 * right now.
66177 	 */
66178 	/* approximation, close enough */
66179 	line = comp_ctx->prev_token.start_line;
66180 	if (line == 0) {
66181 		line = comp_ctx->curr_token.start_line;
66182 	}
66183 #endif
66184 
66185 	instr->ins = ins;
66186 #if defined(DUK_USE_PC2LINE)
66187 	instr->line = (duk_uint32_t) line;
66188 #endif
66189 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66190 	if (line < comp_ctx->curr_func.min_line) {
66191 		comp_ctx->curr_func.min_line = line;
66192 	}
66193 	if (line > comp_ctx->curr_func.max_line) {
66194 		comp_ctx->curr_func.max_line = line;
66195 	}
66196 #endif
66197 
66198 	/* Limit checks for bytecode byte size and line number. */
66199 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
66200 		goto fail_bc_limit;
66201 	}
66202 #if defined(DUK_USE_PC2LINE) && defined(DUK_USE_ESBC_LIMITS)
66203 #if defined(DUK_USE_BUFLEN16)
66204 	/* Buffer length is bounded to 0xffff automatically, avoid compile warning. */
66205 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66206 		goto fail_bc_limit;
66207 	}
66208 #else
66209 	if (DUK_UNLIKELY(line > DUK_USE_ESBC_MAX_LINENUMBER)) {
66210 		goto fail_bc_limit;
66211 	}
66212 #endif
66213 #endif
66214 
66215 	return;
66216 
66217   fail_bc_limit:
66218 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
66219 	DUK_WO_NORETURN(return;);
66220 }
66221 
66222 /* Update function min/max line from current token.  Needed to improve
66223  * function line range information for debugging, so that e.g. opening
66224  * curly brace is covered by line range even when no opcodes are emitted
66225  * for the line containing the brace.
66226  */
66227 DUK_LOCAL void duk__update_lineinfo_currtoken(duk_compiler_ctx *comp_ctx) {
66228 #if defined(DUK_USE_DEBUGGER_SUPPORT)
66229 	duk_int_t line;
66230 
66231 	line = comp_ctx->curr_token.start_line;
66232 	if (line == 0) {
66233 		return;
66234 	}
66235 	if (line < comp_ctx->curr_func.min_line) {
66236 		comp_ctx->curr_func.min_line = line;
66237 	}
66238 	if (line > comp_ctx->curr_func.max_line) {
66239 		comp_ctx->curr_func.max_line = line;
66240 	}
66241 #else
66242 	DUK_UNREF(comp_ctx);
66243 #endif
66244 }
66245 
66246 DUK_LOCAL void duk__emit_op_only(duk_compiler_ctx *comp_ctx, duk_small_uint_t op) {
66247 	duk__emit(comp_ctx, DUK_ENC_OP_ABC(op, 0));
66248 }
66249 
66250 /* Important main primitive. */
66251 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) {
66252 	duk_instr_t ins = 0;
66253 	duk_int_t a_out = -1;
66254 	duk_int_t b_out = -1;
66255 	duk_int_t c_out = -1;
66256 	duk_int_t tmp;
66257 	duk_small_uint_t op = op_flags & 0xffU;
66258 
66259 	DUK_DDD(DUK_DDDPRINT("emit: op_flags=%04lx, a=%ld, b=%ld, c=%ld",
66260 	                     (unsigned long) op_flags, (long) a, (long) b, (long) c));
66261 
66262 	/* We could rely on max temp/const checks: if they don't exceed BC
66263 	 * limit, nothing here can either (just asserts would be enough).
66264 	 * Currently we check for the limits, which provides additional
66265 	 * protection against creating invalid bytecode due to compiler
66266 	 * bugs.
66267 	 */
66268 
66269 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
66270 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
66271 	DUK_ASSERT(DUK__ISREG(a));
66272 	DUK_ASSERT(b != -1);  /* Not 'none'. */
66273 	DUK_ASSERT(c != -1);  /* Not 'none'. */
66274 
66275 	/* Input shuffling happens before the actual operation, while output
66276 	 * shuffling happens afterwards.  Output shuffling decisions are still
66277 	 * made at the same time to reduce branch clutter; output shuffle decisions
66278 	 * are recorded into X_out variables.
66279 	 */
66280 
66281 	/* Slot A: currently no support for reg/const. */
66282 
66283 #if defined(DUK_USE_SHUFFLE_TORTURE)
66284 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
66285 #else
66286 	if (a <= DUK_BC_A_MAX) {
66287 #endif
66288 		;
66289 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
66290 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but shuffle prohibited, a: %ld", (long) a));
66291 		goto error_outofregs;
66292 	} else if (a <= DUK_BC_BC_MAX) {
66293 		comp_ctx->curr_func.needs_shuffle = 1;
66294 		tmp = comp_ctx->curr_func.shuffle1;
66295 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
66296 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
66297 		} else {
66298 			/* Output shuffle needed after main operation */
66299 			a_out = a;
66300 
66301 			/* The DUK_OP_CSVAR output shuffle assumes shuffle registers are
66302 			 * consecutive.
66303 			 */
66304 			DUK_ASSERT((comp_ctx->curr_func.shuffle1 == 0 && comp_ctx->curr_func.shuffle2 == 0) ||
66305 			           (comp_ctx->curr_func.shuffle2 == comp_ctx->curr_func.shuffle1 + 1));
66306 			if (op == DUK_OP_CSVAR) {
66307 				/* For CSVAR the limit is one smaller because output shuffle
66308 				 * must be able to express 'a + 1' in BC.
66309 				 */
66310 				if (a + 1 > DUK_BC_BC_MAX) {
66311 					goto error_outofregs;
66312 				}
66313 			}
66314 		}
66315 		a = tmp;
66316 	} else {
66317 		DUK_D(DUK_DPRINT("out of regs: 'a' (reg) needs shuffling but does not fit into BC, a: %ld", (long) a));
66318 		goto error_outofregs;
66319 	}
66320 
66321 	/* Slot B: reg/const support, mapped to bit 0 of opcode. */
66322 
66323 	if ((b & DUK__CONST_MARKER) != 0) {
66324 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) == 0);
66325 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66326 		b = b & ~DUK__CONST_MARKER;
66327 #if defined(DUK_USE_SHUFFLE_TORTURE)
66328 		if (0) {
66329 #else
66330 		if (b <= 0xff) {
66331 #endif
66332 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
66333 				/* Opcode follows B/C reg/const convention. */
66334 				DUK_ASSERT((op & 0x01) == 0);
66335 				ins |= DUK_ENC_OP_A_B_C(0x01, 0, 0, 0);  /* const flag for B */
66336 			} else {
66337 				DUK_D(DUK_DPRINT("B is const, opcode is not B/C reg/const: %x", op_flags));
66338 			}
66339 		} else if (b <= DUK_BC_BC_MAX) {
66340 			comp_ctx->curr_func.needs_shuffle = 1;
66341 			tmp = comp_ctx->curr_func.shuffle2;
66342 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, b));
66343 			b = tmp;
66344 		} else {
66345 			DUK_D(DUK_DPRINT("out of regs: 'b' (const) needs shuffling but does not fit into BC, b: %ld", (long) b));
66346 			goto error_outofregs;
66347 		}
66348 	} else {
66349 #if defined(DUK_USE_SHUFFLE_TORTURE)
66350 		if (b <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B)) {
66351 #else
66352 		if (b <= 0xff) {
66353 #endif
66354 			;
66355 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_B) {
66356 			if (b > DUK_BC_B_MAX) {
66357 				/* Note: 0xff != DUK_BC_B_MAX */
66358 				DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but shuffle prohibited, b: %ld", (long) b));
66359 				goto error_outofregs;
66360 			}
66361 		} else if (b <= DUK_BC_BC_MAX) {
66362 			comp_ctx->curr_func.needs_shuffle = 1;
66363 			tmp = comp_ctx->curr_func.shuffle2;
66364 			if (op_flags & DUK__EMIT_FLAG_B_IS_TARGET) {
66365 				/* Output shuffle needed after main operation */
66366 				b_out = b;
66367 			}
66368 			if (!(op_flags & DUK__EMIT_FLAG_B_IS_TARGET)) {
66369 				if (op == DUK_OP_MPUTOBJ || op == DUK_OP_MPUTARR) {
66370 					/* Special handling for MPUTOBJ/MPUTARR shuffling.
66371 					 * For each, slot B identifies the first register of a range
66372 					 * of registers, so normal shuffling won't work.  Instead,
66373 					 * an indirect version of the opcode is used.
66374 					 */
66375 					DUK_ASSERT((op_flags & DUK__EMIT_FLAG_B_IS_TARGET) == 0);
66376 					duk__emit_load_int32_noshuffle(comp_ctx, tmp, b);
66377 					DUK_ASSERT(DUK_OP_MPUTOBJI == DUK_OP_MPUTOBJ + 1);
66378 					DUK_ASSERT(DUK_OP_MPUTARRI == DUK_OP_MPUTARR + 1);
66379 					op_flags++;  /* indirect opcode follows direct */
66380 				} else {
66381 					duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, b));
66382 				}
66383 			}
66384 			b = tmp;
66385 		} else {
66386 			DUK_D(DUK_DPRINT("out of regs: 'b' (reg) needs shuffling but does not fit into BC, b: %ld", (long) b));
66387 			goto error_outofregs;
66388 		}
66389 	}
66390 
66391 	/* Slot C: reg/const support, mapped to bit 1 of opcode. */
66392 
66393 	if ((c & DUK__CONST_MARKER) != 0) {
66394 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) == 0);
66395 		DUK_ASSERT((op_flags & DUK__EMIT_FLAG_C_IS_TARGET) == 0);
66396 		c = c & ~DUK__CONST_MARKER;
66397 #if defined(DUK_USE_SHUFFLE_TORTURE)
66398 		if (0) {
66399 #else
66400 		if (c <= 0xff) {
66401 #endif
66402 			if (op_flags & DUK__EMIT_FLAG_BC_REGCONST) {
66403 				/* Opcode follows B/C reg/const convention. */
66404 				DUK_ASSERT((op & 0x02) == 0);
66405 				ins |= DUK_ENC_OP_A_B_C(0x02, 0, 0, 0);  /* const flag for C */
66406 			} else {
66407 				DUK_D(DUK_DPRINT("C is const, opcode is not B/C reg/const: %x", op_flags));
66408 			}
66409 		} else if (c <= DUK_BC_BC_MAX) {
66410 			comp_ctx->curr_func.needs_shuffle = 1;
66411 			tmp = comp_ctx->curr_func.shuffle3;
66412 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDCONST, tmp, c));
66413 			c = tmp;
66414 		} else {
66415 			DUK_D(DUK_DPRINT("out of regs: 'c' (const) needs shuffling but does not fit into BC, c: %ld", (long) c));
66416 			goto error_outofregs;
66417 		}
66418 	} else {
66419 #if defined(DUK_USE_SHUFFLE_TORTURE)
66420 		if (c <= 0xff && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C)) {
66421 #else
66422 		if (c <= 0xff) {
66423 #endif
66424 			;
66425 		} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_C) {
66426 			if (c > DUK_BC_C_MAX) {
66427 				/* Note: 0xff != DUK_BC_C_MAX */
66428 				DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but shuffle prohibited, c: %ld", (long) c));
66429 				goto error_outofregs;
66430 			}
66431 		} else if (c <= DUK_BC_BC_MAX) {
66432 			comp_ctx->curr_func.needs_shuffle = 1;
66433 			tmp = comp_ctx->curr_func.shuffle3;
66434 			if (op_flags & DUK__EMIT_FLAG_C_IS_TARGET) {
66435 				/* Output shuffle needed after main operation */
66436 				c_out = c;
66437 			} else {
66438 				duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, c));
66439 			}
66440 			c = tmp;
66441 		} else {
66442 			DUK_D(DUK_DPRINT("out of regs: 'c' (reg) needs shuffling but does not fit into BC, c: %ld", (long) c));
66443 			goto error_outofregs;
66444 		}
66445 	}
66446 
66447 	/* Main operation */
66448 
66449 	DUK_ASSERT(a >= DUK_BC_A_MIN);
66450 	DUK_ASSERT(a <= DUK_BC_A_MAX);
66451 	DUK_ASSERT(b >= DUK_BC_B_MIN);
66452 	DUK_ASSERT(b <= DUK_BC_B_MAX);
66453 	DUK_ASSERT(c >= DUK_BC_C_MIN);
66454 	DUK_ASSERT(c <= DUK_BC_C_MAX);
66455 
66456 	ins |= DUK_ENC_OP_A_B_C(op_flags & 0xff, a, b, c);
66457 	duk__emit(comp_ctx, ins);
66458 
66459 	/* NEXTENUM needs a jump slot right after the main instruction.
66460 	 * When the JUMP is taken, output spilling is not needed so this
66461 	 * workaround is possible.  The jump slot PC is exceptionally
66462 	 * plumbed through comp_ctx to minimize call sites.
66463 	 */
66464 	if (op_flags & DUK__EMIT_FLAG_RESERVE_JUMPSLOT) {
66465 		comp_ctx->emit_jumpslot_pc = duk__get_current_pc(comp_ctx);
66466 		duk__emit_abc(comp_ctx, DUK_OP_JUMP, 0);
66467 	}
66468 
66469 	/* Output shuffling: only one output register is realistically possible.
66470 	 *
66471 	 * (Zero would normally be an OK marker value: if the target register
66472 	 * was zero, it would never be shuffled.  But with DUK_USE_SHUFFLE_TORTURE
66473 	 * this is no longer true, so use -1 as a marker instead.)
66474 	 */
66475 
66476 	if (a_out >= 0) {
66477 		DUK_ASSERT(b_out < 0);
66478 		DUK_ASSERT(c_out < 0);
66479 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a, a_out));
66480 
66481 		if (op == DUK_OP_CSVAR) {
66482 			/* Special handling for CSVAR shuffling.  The variable lookup
66483 			 * results in a <value, this binding> pair in successive
66484 			 * registers so use two shuffle registers and two output
66485 			 * loads.  (In practice this is dead code because temp/const
66486 			 * limit is reached first.)
66487 			 */
66488 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, a + 1, a_out + 1));
66489 		}
66490 	} else if (b_out >= 0) {
66491 		DUK_ASSERT(a_out < 0);
66492 		DUK_ASSERT(c_out < 0);
66493 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, b, b_out));
66494 	} else if (c_out >= 0) {
66495 		DUK_ASSERT(b_out < 0);
66496 		DUK_ASSERT(c_out < 0);
66497 		duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, c, c_out));
66498 	}
66499 
66500 	return;
66501 
66502  error_outofregs:
66503 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66504 	DUK_WO_NORETURN(return;);
66505 }
66506 
66507 /* For many of the helpers below it'd be technically correct to add
66508  * "no shuffle" flags for parameters passed in as zero.  For example,
66509  * duk__emit_a_b() should call duk__emit_a_b_c() with C set to 0, and
66510  * DUK__EMIT_FLAG_NO_SHUFFLE_C added to op_flags.  However, since the
66511  * C value is 0, it'll never get shuffled so adding the flag is just
66512  * unnecessary additional code.  This is unfortunately not true for
66513  * "shuffle torture" mode which needs special handling.
66514  */
66515 
66516 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) {
66517 #if defined(DUK_USE_SHUFFLE_TORTURE)
66518 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_C;
66519 #endif
66520 	duk__emit_a_b_c(comp_ctx, op_flags, a, b, 0);
66521 }
66522 
66523 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) {
66524 #if defined(DUK_USE_SHUFFLE_TORTURE)
66525 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
66526 #endif
66527 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, c);
66528 }
66529 
66530 #if 0  /* unused */
66531 DUK_LOCAL void duk__emit_a(duk_compiler_ctx *comp_ctx, int op_flags, int a) {
66532 #if defined(DUK_USE_SHUFFLE_TORTURE)
66533 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_B | DUK__EMIT_FLAG_NO_SHUFFLE_C;
66534 #endif
66535 	duk__emit_a_b_c(comp_ctx, op_flags, a, 0, 0);
66536 }
66537 #endif
66538 
66539 #if 0  /* unused */
66540 DUK_LOCAL void duk__emit_b(duk_compiler_ctx *comp_ctx, duk_small_uint_t op_flags, duk_regconst_t b) {
66541 #if defined(DUK_USE_SHUFFLE_TORTURE)
66542 	op_flags |= DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_NO_SHUFFLE_C;
66543 #endif
66544 	duk__emit_a_b_c(comp_ctx, op_flags, 0, b, 0);
66545 }
66546 #endif
66547 
66548 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) {
66549 	duk_instr_t ins;
66550 	duk_int_t tmp;
66551 
66552 	/* allow caller to give a const number with the DUK__CONST_MARKER */
66553 	DUK_ASSERT(bc != -1);  /* Not 'none'. */
66554 	bc = bc & (~DUK__CONST_MARKER);
66555 
66556 	DUK_ASSERT_DISABLE((op_flags & 0xff) >= DUK_BC_OP_MIN);  /* unsigned */
66557 	DUK_ASSERT((op_flags & 0xff) <= DUK_BC_OP_MAX);
66558 	DUK_ASSERT(bc >= DUK_BC_BC_MIN);
66559 	DUK_ASSERT(bc <= DUK_BC_BC_MAX);
66560 	DUK_ASSERT((bc & DUK__CONST_MARKER) == 0);
66561 
66562 	if (bc <= DUK_BC_BC_MAX) {
66563 		;
66564 	} else {
66565 		/* No BC shuffling now. */
66566 		goto error_outofregs;
66567 	}
66568 
66569 #if defined(DUK_USE_SHUFFLE_TORTURE)
66570 	if (a <= DUK_BC_A_MAX && (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A)) {
66571 #else
66572 	if (a <= DUK_BC_A_MAX) {
66573 #endif
66574 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, a, bc);
66575 		duk__emit(comp_ctx, ins);
66576 	} else if (op_flags & DUK__EMIT_FLAG_NO_SHUFFLE_A) {
66577 		goto error_outofregs;
66578 	} else if ((op_flags & 0xf0U) == DUK_OP_CALL0) {
66579 		comp_ctx->curr_func.needs_shuffle = 1;
66580 		tmp = comp_ctx->curr_func.shuffle1;
66581 		duk__emit_load_int32_noshuffle(comp_ctx, tmp, a);
66582 		op_flags |= DUK_BC_CALL_FLAG_INDIRECT;
66583 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
66584 		duk__emit(comp_ctx, ins);
66585 	} else if (a <= DUK_BC_BC_MAX) {
66586 		comp_ctx->curr_func.needs_shuffle = 1;
66587 		tmp = comp_ctx->curr_func.shuffle1;
66588 		ins = DUK_ENC_OP_A_BC(op_flags & 0xff, tmp, bc);
66589 		if (op_flags & DUK__EMIT_FLAG_A_IS_SOURCE) {
66590 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_LDREG, tmp, a));
66591 			duk__emit(comp_ctx, ins);
66592 		} else {
66593 			duk__emit(comp_ctx, ins);
66594 			duk__emit(comp_ctx, DUK_ENC_OP_A_BC(DUK_OP_STREG, tmp, a));
66595 		}
66596 	} else {
66597 		goto error_outofregs;
66598 	}
66599 	return;
66600 
66601  error_outofregs:
66602 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66603 	DUK_WO_NORETURN(return;);
66604 }
66605 
66606 DUK_LOCAL void duk__emit_bc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t bc) {
66607 #if defined(DUK_USE_SHUFFLE_TORTURE)
66608 	op |= DUK__EMIT_FLAG_NO_SHUFFLE_A;
66609 #endif
66610 	duk__emit_a_bc(comp_ctx, op, 0, bc);
66611 }
66612 
66613 DUK_LOCAL void duk__emit_abc(duk_compiler_ctx *comp_ctx, duk_small_uint_t op, duk_regconst_t abc) {
66614 	duk_instr_t ins;
66615 
66616 	DUK_ASSERT_DISABLE(op >= DUK_BC_OP_MIN);  /* unsigned */
66617 	DUK_ASSERT(op <= DUK_BC_OP_MAX);
66618 	DUK_ASSERT_DISABLE(abc >= DUK_BC_ABC_MIN);  /* unsigned */
66619 	DUK_ASSERT(abc <= DUK_BC_ABC_MAX);
66620 	DUK_ASSERT((abc & DUK__CONST_MARKER) == 0);
66621 	DUK_ASSERT(abc != -1);  /* Not 'none'. */
66622 
66623 	if (abc <= DUK_BC_ABC_MAX) {
66624 		;
66625 	} else {
66626 		goto error_outofregs;
66627 	}
66628 	ins = DUK_ENC_OP_ABC(op, abc);
66629 	DUK_DDD(DUK_DDDPRINT("duk__emit_abc: 0x%08lx line=%ld pc=%ld op=%ld (%!C) abc=%ld (%!I)",
66630 	                     (unsigned long) ins, (long) comp_ctx->curr_token.start_line,
66631 	                     (long) duk__get_current_pc(comp_ctx), (long) op, (long) op,
66632 	                     (long) abc, (duk_instr_t) ins));
66633 	duk__emit(comp_ctx, ins);
66634 	return;
66635 
66636  error_outofregs:
66637 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66638 	DUK_WO_NORETURN(return;);
66639 }
66640 
66641 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) {
66642 	/* XXX: Shuffling support could be implemented here so that LDINT+LDINTX
66643 	 * would only shuffle once (instead of twice).  The current code works
66644 	 * though, and has a smaller compiler footprint.
66645 	 */
66646 
66647 	if ((val >= (duk_int32_t) DUK_BC_BC_MIN - (duk_int32_t) DUK_BC_LDINT_BIAS) &&
66648 	    (val <= (duk_int32_t) DUK_BC_BC_MAX - (duk_int32_t) DUK_BC_LDINT_BIAS)) {
66649 		DUK_DDD(DUK_DDDPRINT("emit LDINT to reg %ld for %ld", (long) reg, (long) val));
66650 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (val + (duk_int32_t) DUK_BC_LDINT_BIAS));
66651 	} else {
66652 		duk_int32_t hi = val >> DUK_BC_LDINTX_SHIFT;
66653 		duk_int32_t lo = val & ((((duk_int32_t) 1) << DUK_BC_LDINTX_SHIFT) - 1);
66654 		DUK_ASSERT(lo >= 0);
66655 		DUK_DDD(DUK_DDDPRINT("emit LDINT+LDINTX to reg %ld for %ld -> hi %ld, lo %ld",
66656 		                     (long) reg, (long) val, (long) hi, (long) lo));
66657 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINT | op_flags, reg, (duk_regconst_t) (hi + (duk_int32_t) DUK_BC_LDINT_BIAS));
66658 		duk__emit_a_bc(comp_ctx, DUK_OP_LDINTX | op_flags, reg, (duk_regconst_t) lo);
66659 	}
66660 }
66661 
66662 DUK_LOCAL void duk__emit_load_int32(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66663 	duk__emit_load_int32_raw(comp_ctx, reg, val, 0 /*op_flags*/);
66664 }
66665 
66666 #if defined(DUK_USE_SHUFFLE_TORTURE)
66667 /* Used by duk__emit*() calls so that we don't shuffle the loadints that
66668  * are needed to handle indirect opcodes.
66669  */
66670 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66671 	duk__emit_load_int32_raw(comp_ctx, reg, val, DUK__EMIT_FLAG_NO_SHUFFLE_A /*op_flags*/);
66672 }
66673 #else
66674 DUK_LOCAL void duk__emit_load_int32_noshuffle(duk_compiler_ctx *comp_ctx, duk_regconst_t reg, duk_int32_t val) {
66675 	/* When torture not enabled, can just use the same helper because
66676 	 * 'reg' won't get spilled.
66677 	 */
66678 	DUK_ASSERT(reg <= DUK_BC_A_MAX);
66679 	duk__emit_load_int32(comp_ctx, reg, val);
66680 }
66681 #endif
66682 
66683 DUK_LOCAL void duk__emit_jump(duk_compiler_ctx *comp_ctx, duk_int_t target_pc) {
66684 	duk_int_t curr_pc;
66685 	duk_int_t offset;
66686 
66687 	curr_pc = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
66688 	offset = (duk_int_t) target_pc - (duk_int_t) curr_pc - 1;
66689 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS >= DUK_BC_ABC_MIN);
66690 	DUK_ASSERT(offset + DUK_BC_JUMP_BIAS <= DUK_BC_ABC_MAX);
66691 	duk__emit_abc(comp_ctx, DUK_OP_JUMP, (duk_regconst_t) (offset + DUK_BC_JUMP_BIAS));
66692 }
66693 
66694 DUK_LOCAL duk_int_t duk__emit_jump_empty(duk_compiler_ctx *comp_ctx) {
66695 	duk_int_t ret;
66696 
66697 	ret = duk__get_current_pc(comp_ctx);  /* useful for patching jumps later */
66698 	duk__emit_op_only(comp_ctx, DUK_OP_JUMP);
66699 	return ret;
66700 }
66701 
66702 /* Insert an empty jump in the middle of code emitted earlier.  This is
66703  * currently needed for compiling for-in.
66704  */
66705 DUK_LOCAL void duk__insert_jump_entry(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
66706 #if defined(DUK_USE_PC2LINE)
66707 	duk_int_t line;
66708 #endif
66709 	duk_compiler_instr *instr;
66710 	duk_size_t offset;
66711 
66712 	DUK_ASSERT(jump_pc >= 0);
66713 	offset = (duk_size_t) jump_pc * sizeof(duk_compiler_instr);
66714 	instr = (duk_compiler_instr *) (void *)
66715 	        DUK_BW_INSERT_ENSURE_AREA(comp_ctx->thr,
66716 	                                  &comp_ctx->curr_func.bw_code,
66717 	                                  offset,
66718 	                                  sizeof(duk_compiler_instr));
66719 
66720 #if defined(DUK_USE_PC2LINE)
66721 	line = comp_ctx->curr_token.start_line;  /* approximation, close enough */
66722 #endif
66723 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, 0);
66724 #if defined(DUK_USE_PC2LINE)
66725 	instr->line = (duk_uint32_t) line;
66726 #endif
66727 
66728 	DUK_BW_ADD_PTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code, sizeof(duk_compiler_instr));
66729 	if (DUK_UNLIKELY(DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) > DUK_USE_ESBC_MAX_BYTES)) {
66730 		goto fail_bc_limit;
66731 	}
66732 	return;
66733 
66734   fail_bc_limit:
66735 	DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_BYTECODE_LIMIT);
66736 	DUK_WO_NORETURN(return;);
66737 }
66738 
66739 /* Does not assume that jump_pc contains a DUK_OP_JUMP previously; this is intentional
66740  * to allow e.g. an INVALID opcode be overwritten with a JUMP (label management uses this).
66741  */
66742 DUK_LOCAL void duk__patch_jump(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc, duk_int_t target_pc) {
66743 	duk_compiler_instr *instr;
66744 	duk_int_t offset;
66745 
66746 	/* allow negative PCs, behave as a no-op */
66747 	if (jump_pc < 0) {
66748 		DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): nop call, jump_pc=%ld (<0), target_pc=%ld",
66749 		                     (long) jump_pc, (long) target_pc));
66750 		return;
66751 	}
66752 	DUK_ASSERT(jump_pc >= 0);
66753 
66754 	/* XXX: range assert */
66755 	instr = duk__get_instr_ptr(comp_ctx, jump_pc);
66756 	DUK_ASSERT(instr != NULL);
66757 
66758 	/* XXX: range assert */
66759 	offset = target_pc - jump_pc - 1;
66760 
66761 	instr->ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, offset + DUK_BC_JUMP_BIAS);
66762 	DUK_DDD(DUK_DDDPRINT("duk__patch_jump(): jump_pc=%ld, target_pc=%ld, offset=%ld",
66763 	                     (long) jump_pc, (long) target_pc, (long) offset));
66764 }
66765 
66766 DUK_LOCAL void duk__patch_jump_here(duk_compiler_ctx *comp_ctx, duk_int_t jump_pc) {
66767 	duk__patch_jump(comp_ctx, jump_pc, duk__get_current_pc(comp_ctx));
66768 }
66769 
66770 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) {
66771 	duk_compiler_instr *instr;
66772 
66773 	DUK_ASSERT(DUK__ISREG(reg_catch));
66774 
66775 	instr = duk__get_instr_ptr(comp_ctx, ldconst_pc);
66776 	DUK_ASSERT(DUK_DEC_OP(instr->ins) == DUK_OP_LDCONST);
66777 	DUK_ASSERT(instr != NULL);
66778 	if (const_varname & DUK__CONST_MARKER) {
66779 		/* Have a catch variable. */
66780 		const_varname = const_varname & (~DUK__CONST_MARKER);
66781 		if (reg_catch > DUK_BC_BC_MAX || const_varname > DUK_BC_BC_MAX) {
66782 			/* Catch attempts to use out-of-range reg/const.  Without this
66783 			 * check Duktape 0.12.0 could generate invalid code which caused
66784 			 * an assert failure on execution.  This error is triggered e.g.
66785 			 * for functions with a lot of constants and a try-catch statement.
66786 			 * Shuffling or opcode semantics change is needed to fix the issue.
66787 			 * See: test-bug-trycatch-many-constants.js.
66788 			 */
66789 			DUK_D(DUK_DPRINT("failed to patch trycatch: flags=%ld, reg_catch=%ld, const_varname=%ld (0x%08lx)",
66790 			                 (long) flags, (long) reg_catch, (long) const_varname, (long) const_varname));
66791 			DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_REG_LIMIT);
66792 			DUK_WO_NORETURN(return;);
66793 		}
66794 		instr->ins |= DUK_ENC_OP_A_BC(0, 0, const_varname);
66795 	} else {
66796 		/* No catch variable, e.g. a try-finally; replace LDCONST with
66797 		 * NOP to avoid a bogus LDCONST.
66798 		 */
66799 		instr->ins = DUK_ENC_OP(DUK_OP_NOP);
66800 	}
66801 
66802 	instr = duk__get_instr_ptr(comp_ctx, trycatch_pc);
66803 	DUK_ASSERT(instr != NULL);
66804 	DUK_ASSERT_DISABLE(flags >= DUK_BC_A_MIN);
66805 	DUK_ASSERT(flags <= DUK_BC_A_MAX);
66806 	instr->ins = DUK_ENC_OP_A_BC(DUK_OP_TRYCATCH, flags, reg_catch);
66807 }
66808 
66809 DUK_LOCAL void duk__emit_if_false_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
66810 	duk_small_uint_t op;
66811 
66812 	op = DUK__ISREG(regconst) ? DUK_OP_IFFALSE_R : DUK_OP_IFFALSE_C;
66813 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
66814 }
66815 
66816 DUK_LOCAL void duk__emit_if_true_skip(duk_compiler_ctx *comp_ctx, duk_regconst_t regconst) {
66817 	duk_small_uint_t op;
66818 
66819 	op = DUK__ISREG(regconst) ? DUK_OP_IFTRUE_R : DUK_OP_IFTRUE_C;
66820 	duk__emit_bc(comp_ctx, op, regconst);  /* helper will remove const flag */
66821 }
66822 
66823 DUK_LOCAL void duk__emit_invalid(duk_compiler_ctx *comp_ctx) {
66824 	duk__emit_op_only(comp_ctx, DUK_OP_INVALID);
66825 }
66826 
66827 /*
66828  *  Peephole optimizer for finished bytecode.
66829  *
66830  *  Does not remove opcodes; currently only straightens out unconditional
66831  *  jump chains which are generated by several control structures.
66832  */
66833 
66834 DUK_LOCAL void duk__peephole_optimize_bytecode(duk_compiler_ctx *comp_ctx) {
66835 	duk_compiler_instr *bc;
66836 	duk_small_uint_t iter;
66837 	duk_int_t i, n;
66838 	duk_int_t count_opt;
66839 
66840 	bc = (duk_compiler_instr *) (void *) DUK_BW_GET_BASEPTR(comp_ctx->thr, &comp_ctx->curr_func.bw_code);
66841 #if defined(DUK_USE_BUFLEN16)
66842 	/* No need to assert, buffer size maximum is 0xffff. */
66843 #else
66844 	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 */
66845 #endif
66846 	n = (duk_int_t) (DUK_BW_GET_SIZE(comp_ctx->thr, &comp_ctx->curr_func.bw_code) / sizeof(duk_compiler_instr));
66847 
66848 	for (iter = 0; iter < DUK_COMPILER_PEEPHOLE_MAXITER; iter++) {
66849 		count_opt = 0;
66850 
66851 		for (i = 0; i < n; i++) {
66852 			duk_instr_t ins;
66853 			duk_int_t target_pc1;
66854 			duk_int_t target_pc2;
66855 
66856 			ins = bc[i].ins;
66857 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
66858 				continue;
66859 			}
66860 
66861 			target_pc1 = i + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
66862 			DUK_DDD(DUK_DDDPRINT("consider jump at pc %ld; target_pc=%ld", (long) i, (long) target_pc1));
66863 			DUK_ASSERT(target_pc1 >= 0);
66864 			DUK_ASSERT(target_pc1 < n);
66865 
66866 			/* Note: if target_pc1 == i, we'll optimize a jump to itself.
66867 			 * This does not need to be checked for explicitly; the case
66868 			 * is rare and max iter breaks us out.
66869 			 */
66870 
66871 			ins = bc[target_pc1].ins;
66872 			if (DUK_DEC_OP(ins) != DUK_OP_JUMP) {
66873 				continue;
66874 			}
66875 
66876 			target_pc2 = target_pc1 + 1 + (duk_int_t) DUK_DEC_ABC(ins) - (duk_int_t) DUK_BC_JUMP_BIAS;
66877 
66878 			DUK_DDD(DUK_DDDPRINT("optimizing jump at pc %ld; old target is %ld -> new target is %ld",
66879 			                     (long) i, (long) target_pc1, (long) target_pc2));
66880 
66881 			bc[i].ins = DUK_ENC_OP_ABC(DUK_OP_JUMP, target_pc2 - (i + 1) + DUK_BC_JUMP_BIAS);
66882 
66883 			count_opt++;
66884 		}
66885 
66886 		DUK_DD(DUK_DDPRINT("optimized %ld jumps on peephole round %ld", (long) count_opt, (long) (iter + 1)));
66887 
66888 		if (count_opt == 0) {
66889 			break;
66890 		}
66891 	}
66892 }
66893 
66894 /*
66895  *  Intermediate value helpers
66896  */
66897 
66898 /* Flags for intermediate value coercions.  A flag for using a forced reg
66899  * is not needed, the forced_reg argument suffices and generates better
66900  * code (it is checked as it is used).
66901  */
66902 /* XXX: DUK__IVAL_FLAG_REQUIRE_SHORT is passed but not currently implemented
66903  * by ispec/ivalue operations.
66904  */
66905 #define DUK__IVAL_FLAG_ALLOW_CONST          (1 << 0)  /* allow a constant to be returned */
66906 #define DUK__IVAL_FLAG_REQUIRE_TEMP         (1 << 1)  /* require a (mutable) temporary as a result (or a const if allowed) */
66907 #define DUK__IVAL_FLAG_REQUIRE_SHORT        (1 << 2)  /* require a short (8-bit) reg/const which fits into bytecode B/C slot */
66908 
66909 /* XXX: some code might benefit from DUK__SETTEMP_IFTEMP(thr,x) */
66910 
66911 #if 0  /* enable manually for dumping */
66912 #define DUK__DUMP_ISPEC(compctx,ispec) do { duk__dump_ispec((compctx), (ispec)); } while (0)
66913 #define DUK__DUMP_IVALUE(compctx,ivalue) do { duk__dump_ivalue((compctx), (ivalue)); } while (0)
66914 
66915 DUK_LOCAL void duk__dump_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *x) {
66916 	DUK_D(DUK_DPRINT("ispec dump: t=%ld regconst=0x%08lx, valstack_idx=%ld, value=%!T",
66917 	                 (long) x->t, (unsigned long) x->regconst, (long) x->valstack_idx,
66918 	                 duk_get_tval(comp_ctx->thr, x->valstack_idx)));
66919 }
66920 DUK_LOCAL void duk__dump_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66921 	DUK_D(DUK_DPRINT("ivalue dump: t=%ld op=%ld "
66922 	                 "x1={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T} "
66923 	                 "x2={t=%ld regconst=0x%08lx valstack_idx=%ld value=%!T}",
66924 		         (long) x->t, (long) x->op,
66925 	                 (long) x->x1.t, (unsigned long) x->x1.regconst, (long) x->x1.valstack_idx,
66926 	                 duk_get_tval(comp_ctx->thr, x->x1.valstack_idx),
66927 	                 (long) x->x2.t, (unsigned long) x->x2.regconst, (long) x->x2.valstack_idx,
66928 	                 duk_get_tval(comp_ctx->thr, x->x2.valstack_idx)));
66929 }
66930 #else
66931 #define DUK__DUMP_ISPEC(comp_ctx,x) do {} while (0)
66932 #define DUK__DUMP_IVALUE(comp_ctx,x) do {} while (0)
66933 #endif
66934 
66935 DUK_LOCAL void duk__ivalue_regconst(duk_ivalue *x, duk_regconst_t regconst) {
66936 	x->t = DUK_IVAL_PLAIN;
66937 	x->x1.t = DUK_ISPEC_REGCONST;
66938 	x->x1.regconst = regconst;
66939 }
66940 
66941 DUK_LOCAL void duk__ivalue_plain_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66942 	x->t = DUK_IVAL_PLAIN;
66943 	x->x1.t = DUK_ISPEC_VALUE;
66944 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
66945 }
66946 
66947 DUK_LOCAL void duk__ivalue_var_fromstack(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
66948 	x->t = DUK_IVAL_VAR;
66949 	x->x1.t = DUK_ISPEC_VALUE;
66950 	duk_replace(comp_ctx->thr, x->x1.valstack_idx);
66951 }
66952 
66953 DUK_LOCAL_DECL void duk__ivalue_var_hstring(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_hstring *h) {
66954 	DUK_ASSERT(h != NULL);
66955 	duk_push_hstring(comp_ctx->thr, h);
66956 	duk__ivalue_var_fromstack(comp_ctx, x);
66957 }
66958 
66959 DUK_LOCAL void duk__copy_ispec(duk_compiler_ctx *comp_ctx, duk_ispec *src, duk_ispec *dst) {
66960 	dst->t = src->t;
66961 	dst->regconst = src->regconst;
66962 	duk_copy(comp_ctx->thr, src->valstack_idx, dst->valstack_idx);
66963 }
66964 
66965 DUK_LOCAL void duk__copy_ivalue(duk_compiler_ctx *comp_ctx, duk_ivalue *src, duk_ivalue *dst) {
66966 	dst->t = src->t;
66967 	dst->op = src->op;
66968 	dst->x1.t = src->x1.t;
66969 	dst->x1.regconst = src->x1.regconst;
66970 	dst->x2.t = src->x2.t;
66971 	dst->x2.regconst = src->x2.regconst;
66972 	duk_copy(comp_ctx->thr, src->x1.valstack_idx, dst->x1.valstack_idx);
66973 	duk_copy(comp_ctx->thr, src->x2.valstack_idx, dst->x2.valstack_idx);
66974 }
66975 
66976 DUK_LOCAL duk_regconst_t duk__alloctemps(duk_compiler_ctx *comp_ctx, duk_small_int_t num) {
66977 	duk_regconst_t res;
66978 
66979 	res = comp_ctx->curr_func.temp_next;
66980 	comp_ctx->curr_func.temp_next += num;
66981 
66982 	if (comp_ctx->curr_func.temp_next > DUK__MAX_TEMPS) {  /* == DUK__MAX_TEMPS is OK */
66983 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_TEMP_LIMIT);
66984 		DUK_WO_NORETURN(return 0;);
66985 	}
66986 
66987 	/* maintain highest 'used' temporary, needed to figure out nregs of function */
66988 	if (comp_ctx->curr_func.temp_next > comp_ctx->curr_func.temp_max) {
66989 		comp_ctx->curr_func.temp_max = comp_ctx->curr_func.temp_next;
66990 	}
66991 
66992 	return res;
66993 }
66994 
66995 DUK_LOCAL duk_regconst_t duk__alloctemp(duk_compiler_ctx *comp_ctx) {
66996 	return duk__alloctemps(comp_ctx, 1);
66997 }
66998 
66999 DUK_LOCAL void duk__settemp_checkmax(duk_compiler_ctx *comp_ctx, duk_regconst_t temp_next) {
67000 	comp_ctx->curr_func.temp_next = temp_next;
67001 	if (temp_next > comp_ctx->curr_func.temp_max) {
67002 		comp_ctx->curr_func.temp_max = temp_next;
67003 	}
67004 }
67005 
67006 /* get const for value at valstack top */
67007 DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
67008 	duk_hthread *thr = comp_ctx->thr;
67009 	duk_compiler_func *f = &comp_ctx->curr_func;
67010 	duk_tval *tv1;
67011 	duk_int_t i, n, n_check;
67012 
67013 	n = (duk_int_t) duk_get_length(thr, f->consts_idx);
67014 
67015 	tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
67016 	DUK_ASSERT(tv1 != NULL);
67017 
67018 #if defined(DUK_USE_FASTINT)
67019 	/* Explicit check for fastint downgrade. */
67020 	DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
67021 #endif
67022 
67023 	/* Sanity workaround for handling functions with a large number of
67024 	 * constants at least somewhat reasonably.  Otherwise checking whether
67025 	 * we already have the constant would grow very slow (as it is O(N^2)).
67026 	 */
67027 	n_check = (n > DUK__GETCONST_MAX_CONSTS_CHECK ? DUK__GETCONST_MAX_CONSTS_CHECK : n);
67028 	for (i = 0; i < n_check; i++) {
67029 		duk_tval *tv2 = DUK_HOBJECT_A_GET_VALUE_PTR(thr->heap, f->h_consts, i);
67030 
67031 		/* Strict equality is NOT enough, because we cannot use the same
67032 		 * constant for e.g. +0 and -0.
67033 		 */
67034 		if (duk_js_samevalue(tv1, tv2)) {
67035 			DUK_DDD(DUK_DDDPRINT("reused existing constant for %!T -> const index %ld",
67036 			                     (duk_tval *) tv1, (long) i));
67037 			duk_pop(thr);
67038 			return (duk_regconst_t) i | (duk_regconst_t) DUK__CONST_MARKER;
67039 		}
67040 	}
67041 
67042 	if (n > DUK__MAX_CONSTS) {
67043 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_CONST_LIMIT);
67044 		DUK_WO_NORETURN(return 0;);
67045 	}
67046 
67047 	DUK_DDD(DUK_DDDPRINT("allocating new constant for %!T -> const index %ld",
67048 	                     (duk_tval *) tv1, (long) n));
67049 	(void) duk_put_prop_index(thr, f->consts_idx, (duk_uarridx_t) n);  /* invalidates tv1, tv2 */
67050 	return (duk_regconst_t) n | (duk_regconst_t) DUK__CONST_MARKER;
67051 }
67052 
67053 DUK_LOCAL duk_bool_t duk__const_needs_refcount(duk_compiler_ctx *comp_ctx, duk_regconst_t rc) {
67054 #if defined(DUK_USE_REFERENCE_COUNTING)
67055 	duk_compiler_func *f = &comp_ctx->curr_func;
67056 	duk_bool_t ret;
67057 
67058 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67059 	(void) duk_get_prop_index(comp_ctx->thr, f->consts_idx, (duk_uarridx_t) rc);
67060 	ret = !duk_is_number(comp_ctx->thr, -1);  /* now only number/string, so conservative check */
67061 	duk_pop(comp_ctx->thr);
67062 	return ret;
67063 #else
67064 	DUK_UNREF(comp_ctx);
67065 	DUK_UNREF(rc);
67066 	DUK_ASSERT((rc & DUK__CONST_MARKER) == 0);  /* caller removes const marker */
67067 	return 0;
67068 #endif
67069 }
67070 
67071 /* Get the value represented by an duk_ispec to a register or constant.
67072  * The caller can control the result by indicating whether or not:
67073  *
67074  *   (1) a constant is allowed (sometimes the caller needs the result to
67075  *       be in a register)
67076  *
67077  *   (2) a temporary register is required (usually when caller requires
67078  *       the register to be safely mutable; normally either a bound
67079  *       register or a temporary register are both OK)
67080  *
67081  *   (3) a forced register target needs to be used
67082  *
67083  * Bytecode may be emitted to generate the necessary value.  The return
67084  * value is either a register or a constant.
67085  */
67086 
67087 DUK_LOCAL
67088 duk_regconst_t duk__ispec_toregconst_raw(duk_compiler_ctx *comp_ctx,
67089                                          duk_ispec *x,
67090                                          duk_regconst_t forced_reg,
67091                                          duk_small_uint_t flags) {
67092 	duk_hthread *thr = comp_ctx->thr;
67093 
67094 	DUK_DDD(DUK_DDDPRINT("duk__ispec_toregconst_raw(): x={%ld:%ld:%!T}, "
67095 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
67096 	                     (long) x->t,
67097 	                     (long) x->regconst,
67098 	                     (duk_tval *) duk_get_tval(thr, x->valstack_idx),
67099 	                     (long) forced_reg,
67100 	                     (unsigned long) flags,
67101 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
67102 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
67103 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
67104 
67105 	switch (x->t) {
67106 	case DUK_ISPEC_VALUE: {
67107 		duk_tval *tv;
67108 
67109 		tv = DUK_GET_TVAL_POSIDX(thr, x->valstack_idx);
67110 		DUK_ASSERT(tv != NULL);
67111 
67112 		switch (DUK_TVAL_GET_TAG(tv)) {
67113 		case DUK_TAG_UNDEFINED: {
67114 			/* Note: although there is no 'undefined' literal, undefined
67115 			 * values can occur during compilation as a result of e.g.
67116 			 * the 'void' operator.
67117 			 */
67118 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67119 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, dest);
67120 			return dest;
67121 		}
67122 		case DUK_TAG_NULL: {
67123 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67124 			duk__emit_bc(comp_ctx, DUK_OP_LDNULL, dest);
67125 			return dest;
67126 		}
67127 		case DUK_TAG_BOOLEAN: {
67128 			duk_regconst_t dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67129 			duk__emit_bc(comp_ctx,
67130 			             (DUK_TVAL_GET_BOOLEAN(tv) ? DUK_OP_LDTRUE : DUK_OP_LDFALSE),
67131 			             dest);
67132 			return dest;
67133 		}
67134 		case DUK_TAG_POINTER: {
67135 			DUK_UNREACHABLE();
67136 			break;
67137 		}
67138 		case DUK_TAG_STRING: {
67139 			duk_hstring *h;
67140 			duk_regconst_t dest;
67141 			duk_regconst_t constidx;
67142 
67143 			h = DUK_TVAL_GET_STRING(tv);
67144 			DUK_UNREF(h);
67145 			DUK_ASSERT(h != NULL);
67146 
67147 #if 0  /* XXX: to be implemented? */
67148 			/* Use special opcodes to load short strings */
67149 			if (DUK_HSTRING_GET_BYTELEN(h) <= 2) {
67150 				/* Encode into a single opcode (18 bits can encode 1-2 bytes + length indicator) */
67151 			} else if (DUK_HSTRING_GET_BYTELEN(h) <= 6) {
67152 				/* Encode into a double constant (53 bits can encode 6*8 = 48 bits + 3-bit length */
67153 			}
67154 #endif
67155 			duk_dup(thr, x->valstack_idx);
67156 			constidx = duk__getconst(comp_ctx);
67157 
67158 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67159 				return constidx;
67160 			}
67161 
67162 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67163 			duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67164 			return dest;
67165 		}
67166 		case DUK_TAG_OBJECT: {
67167 			DUK_UNREACHABLE();
67168 			break;
67169 		}
67170 		case DUK_TAG_BUFFER: {
67171 			DUK_UNREACHABLE();
67172 			break;
67173 		}
67174 		case DUK_TAG_LIGHTFUNC: {
67175 			DUK_UNREACHABLE();
67176 			break;
67177 		}
67178 #if defined(DUK_USE_FASTINT)
67179 		case DUK_TAG_FASTINT:
67180 #endif
67181 		default: {
67182 			/* number */
67183 			duk_regconst_t dest;
67184 			duk_regconst_t constidx;
67185 			duk_double_t dval;
67186 			duk_int32_t ival;
67187 
67188 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
67189 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
67190 			dval = DUK_TVAL_GET_NUMBER(tv);
67191 
67192 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67193 				/* A number can be loaded either through a constant, using
67194 				 * LDINT, or using LDINT+LDINTX.  LDINT is always a size win,
67195 				 * LDINT+LDINTX is not if the constant is used multiple times.
67196 				 * Currently always prefer LDINT+LDINTX over a double constant.
67197 				 */
67198 
67199 				if (duk_is_whole_get_int32_nonegzero(dval, &ival)) {
67200 					dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67201 					duk__emit_load_int32(comp_ctx, dest, ival);
67202 					return dest;
67203 				}
67204 			}
67205 
67206 			duk_dup(thr, x->valstack_idx);
67207 			constidx = duk__getconst(comp_ctx);
67208 
67209 			if (flags & DUK__IVAL_FLAG_ALLOW_CONST) {
67210 				return constidx;
67211 			} else {
67212 				dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67213 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, constidx);
67214 				return dest;
67215 			}
67216 		}
67217 		}  /* end switch */
67218 		goto fail_internal;  /* never here */
67219 	}
67220 	case DUK_ISPEC_REGCONST: {
67221 		if (forced_reg >= 0) {
67222 			if (DUK__ISCONST(x->regconst)) {
67223 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, forced_reg, x->regconst);
67224 			} else if (x->regconst != forced_reg) {
67225 				duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, forced_reg, x->regconst);
67226 			} else {
67227 				; /* already in correct reg */
67228 			}
67229 			return forced_reg;
67230 		}
67231 
67232 		DUK_ASSERT(forced_reg < 0);
67233 		if (DUK__ISCONST(x->regconst)) {
67234 			if (!(flags & DUK__IVAL_FLAG_ALLOW_CONST)) {
67235 				duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67236 				duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, dest, x->regconst);
67237 				return dest;
67238 			}
67239 			return x->regconst;
67240 		}
67241 
67242 		DUK_ASSERT(forced_reg < 0 && !DUK__ISCONST(x->regconst));
67243 		if ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) && !DUK__ISREG_TEMP(comp_ctx, x->regconst)) {
67244 			duk_regconst_t dest = DUK__ALLOCTEMP(comp_ctx);
67245 			duk__emit_a_bc(comp_ctx, DUK_OP_LDREG, dest, x->regconst);
67246 			return dest;
67247 		}
67248 		return x->regconst;
67249 	}
67250 	default: {
67251 		break;  /* never here */
67252 	}
67253 	}
67254 
67255  fail_internal:
67256 	DUK_ERROR_INTERNAL(thr);
67257 	DUK_WO_NORETURN(return 0;);
67258 }
67259 
67260 DUK_LOCAL void duk__ispec_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ispec *x, duk_regconst_t forced_reg) {
67261 	DUK_ASSERT(forced_reg >= 0);
67262 	(void) duk__ispec_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
67263 }
67264 
67265 /* Coerce an duk_ivalue to a 'plain' value by generating the necessary
67266  * arithmetic operations, property access, or variable access bytecode.
67267  * The duk_ivalue argument ('x') is converted into a plain value as a
67268  * side effect.
67269  */
67270 DUK_LOCAL void duk__ivalue_toplain_raw(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_regconst_t forced_reg) {
67271 	duk_hthread *thr = comp_ctx->thr;
67272 
67273 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toplain_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
67274 	                     "forced_reg=%ld",
67275 	                     (long) x->t, (long) x->op,
67276 	                     (long) x->x1.t, (long) x->x1.regconst,
67277 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
67278 	                     (long) x->x2.t, (long) x->x2.regconst,
67279 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
67280 	                     (long) forced_reg));
67281 
67282 	switch (x->t) {
67283 	case DUK_IVAL_PLAIN: {
67284 		return;
67285 	}
67286 	/* XXX: support unary arithmetic ivalues (useful?) */
67287 	case DUK_IVAL_ARITH: {
67288 		duk_regconst_t arg1;
67289 		duk_regconst_t arg2;
67290 		duk_regconst_t dest;
67291 		duk_tval *tv1;
67292 		duk_tval *tv2;
67293 
67294 		DUK_DDD(DUK_DDDPRINT("arith to plain conversion"));
67295 
67296 		/* inline arithmetic check for constant values */
67297 		/* XXX: use the exactly same arithmetic function here as in executor */
67298 		if (x->x1.t == DUK_ISPEC_VALUE && x->x2.t == DUK_ISPEC_VALUE && x->t == DUK_IVAL_ARITH) {
67299 			tv1 = DUK_GET_TVAL_POSIDX(thr, x->x1.valstack_idx);
67300 			tv2 = DUK_GET_TVAL_POSIDX(thr, x->x2.valstack_idx);
67301 			DUK_ASSERT(tv1 != NULL);
67302 			DUK_ASSERT(tv2 != NULL);
67303 
67304 			DUK_DDD(DUK_DDDPRINT("arith: tv1=%!T, tv2=%!T",
67305 			                     (duk_tval *) tv1,
67306 			                     (duk_tval *) tv2));
67307 
67308 			if (DUK_TVAL_IS_NUMBER(tv1) && DUK_TVAL_IS_NUMBER(tv2)) {
67309 				duk_double_t d1 = DUK_TVAL_GET_NUMBER(tv1);
67310 				duk_double_t d2 = DUK_TVAL_GET_NUMBER(tv2);
67311 				duk_double_t d3;
67312 				duk_bool_t accept_fold = 1;
67313 
67314 				DUK_DDD(DUK_DDDPRINT("arith inline check: d1=%lf, d2=%lf, op=%ld",
67315 				                     (double) d1, (double) d2, (long) x->op));
67316 				switch (x->op) {
67317 				case DUK_OP_ADD: {
67318 					d3 = d1 + d2;
67319 					break;
67320 				}
67321 				case DUK_OP_SUB: {
67322 					d3 = d1 - d2;
67323 					break;
67324 				}
67325 				case DUK_OP_MUL: {
67326 					d3 = d1 * d2;
67327 					break;
67328 				}
67329 				case DUK_OP_DIV: {
67330 					/* Division-by-zero is undefined
67331 					 * behavior, so rely on a helper.
67332 					 */
67333 					d3 = duk_double_div(d1, d2);
67334 					break;
67335 				}
67336 				case DUK_OP_EXP: {
67337 					d3 = (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
67338 					break;
67339 				}
67340 				default: {
67341 					d3 = 0.0;  /* Won't be used, but silence MSVC /W4 warning. */
67342 					accept_fold = 0;
67343 					break;
67344 				}
67345 				}
67346 
67347 				if (accept_fold) {
67348 					duk_double_union du;
67349 					du.d = d3;
67350 					DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
67351 					d3 = du.d;
67352 
67353 					x->t = DUK_IVAL_PLAIN;
67354 					DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67355 					DUK_TVAL_SET_NUMBER(tv1, d3);  /* old value is number: no refcount */
67356 					return;
67357 				}
67358 			} else if (x->op == DUK_OP_ADD && DUK_TVAL_IS_STRING(tv1) && DUK_TVAL_IS_STRING(tv2)) {
67359 				/* Inline string concatenation.  No need to check for
67360 				 * symbols, as all inputs are valid ECMAScript strings.
67361 				 */
67362 				duk_dup(thr, x->x1.valstack_idx);
67363 				duk_dup(thr, x->x2.valstack_idx);
67364 				duk_concat(thr, 2);
67365 				duk_replace(thr, x->x1.valstack_idx);
67366 				x->t = DUK_IVAL_PLAIN;
67367 				DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67368 				return;
67369 			}
67370 		}
67371 
67372 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67373 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67374 
67375 		/* If forced reg, use it as destination.  Otherwise try to
67376 		 * use either coerced ispec if it is a temporary.
67377 		 */
67378 		if (forced_reg >= 0) {
67379 			dest = forced_reg;
67380 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
67381 			dest = arg1;
67382 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
67383 			dest = arg2;
67384 		} else {
67385 			dest = DUK__ALLOCTEMP(comp_ctx);
67386 		}
67387 
67388 		DUK_ASSERT(DUK__ISREG(dest));
67389 		duk__emit_a_b_c(comp_ctx, x->op | DUK__EMIT_FLAG_BC_REGCONST, dest, arg1, arg2);
67390 
67391 		duk__ivalue_regconst(x, dest);
67392 		return;
67393 	}
67394 	case DUK_IVAL_PROP: {
67395 		/* XXX: very similar to DUK_IVAL_ARITH - merge? */
67396 		duk_regconst_t arg1;
67397 		duk_regconst_t arg2;
67398 		duk_regconst_t dest;
67399 
67400 		/* Need a short reg/const, does not have to be a mutable temp. */
67401 		arg1 = duk__ispec_toregconst_raw(comp_ctx, &x->x1, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67402 		arg2 = duk__ispec_toregconst_raw(comp_ctx, &x->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_SHORT /*flags*/);
67403 
67404 		/* Pick a destination register.  If either base value or key
67405 		 * happens to be a temp value, reuse it as the destination.
67406 		 *
67407 		 * XXX: The temp must be a "mutable" one, i.e. such that no
67408 		 * other expression is using it anymore.  Here this should be
67409 		 * the case because the value of a property access expression
67410 		 * is neither the base nor the key, but the lookup result.
67411 		 */
67412 
67413 		if (forced_reg >= 0) {
67414 			dest = forced_reg;
67415 		} else if (DUK__ISREG_TEMP(comp_ctx, arg1)) {
67416 			dest = arg1;
67417 		} else if (DUK__ISREG_TEMP(comp_ctx, arg2)) {
67418 			dest = arg2;
67419 		} else {
67420 			dest = DUK__ALLOCTEMP(comp_ctx);
67421 		}
67422 
67423 		duk__emit_a_b_c(comp_ctx,
67424 		                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
67425 		                dest,
67426 		                arg1,
67427 		                arg2);
67428 
67429 		duk__ivalue_regconst(x, dest);
67430 		return;
67431 	}
67432 	case DUK_IVAL_VAR: {
67433 		/* x1 must be a string */
67434 		duk_regconst_t dest;
67435 		duk_regconst_t reg_varbind;
67436 		duk_regconst_t rc_varname;
67437 
67438 		DUK_ASSERT(x->x1.t == DUK_ISPEC_VALUE);
67439 
67440 		duk_dup(thr, x->x1.valstack_idx);
67441 		if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
67442 			duk__ivalue_regconst(x, reg_varbind);
67443 		} else {
67444 			dest = (forced_reg >= 0 ? forced_reg : DUK__ALLOCTEMP(comp_ctx));
67445 			duk__emit_a_bc(comp_ctx, DUK_OP_GETVAR, dest, rc_varname);
67446 			duk__ivalue_regconst(x, dest);
67447 		}
67448 		return;
67449 	}
67450 	case DUK_IVAL_NONE:
67451 	default: {
67452 		DUK_D(DUK_DPRINT("invalid ivalue type: %ld", (long) x->t));
67453 		break;
67454 	}
67455 	}
67456 
67457 	DUK_ERROR_INTERNAL(thr);
67458 	DUK_WO_NORETURN(return;);
67459 }
67460 
67461 /* evaluate to plain value, no forced register (temp/bound reg both ok) */
67462 DUK_LOCAL void duk__ivalue_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67463 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
67464 }
67465 
67466 /* evaluate to final form (e.g. coerce GETPROP to code), throw away temp */
67467 DUK_LOCAL void duk__ivalue_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67468 	duk_regconst_t temp;
67469 
67470 	/* If duk__ivalue_toplain_raw() allocates a temp, forget it and
67471 	 * restore next temp state.
67472 	 */
67473 	temp = DUK__GETTEMP(comp_ctx);
67474 	duk__ivalue_toplain_raw(comp_ctx, x, -1 /*forced_reg*/);
67475 	DUK__SETTEMP(comp_ctx, temp);
67476 }
67477 
67478 /* Coerce an duk_ivalue to a register or constant; result register may
67479  * be a temp or a bound register.
67480  *
67481  * The duk_ivalue argument ('x') is converted into a regconst as a
67482  * side effect.
67483  */
67484 DUK_LOCAL
67485 duk_regconst_t duk__ivalue_toregconst_raw(duk_compiler_ctx *comp_ctx,
67486                                           duk_ivalue *x,
67487                                           duk_regconst_t forced_reg,
67488                                           duk_small_uint_t flags) {
67489 	duk_hthread *thr = comp_ctx->thr;
67490 	duk_regconst_t reg;
67491 	DUK_UNREF(thr);
67492 
67493 	DUK_DDD(DUK_DDDPRINT("duk__ivalue_toregconst_raw(): x={t=%ld,op=%ld,x1={%ld:%ld:%!T},x2={%ld:%ld:%!T}}, "
67494 	                     "forced_reg=%ld, flags 0x%08lx: allow_const=%ld require_temp=%ld require_short=%ld",
67495 	                     (long) x->t, (long) x->op,
67496 	                     (long) x->x1.t, (long) x->x1.regconst,
67497 	                     (duk_tval *) duk_get_tval(thr, x->x1.valstack_idx),
67498 	                     (long) x->x2.t, (long) x->x2.regconst,
67499 	                     (duk_tval *) duk_get_tval(thr, x->x2.valstack_idx),
67500 	                     (long) forced_reg,
67501 	                     (unsigned long) flags,
67502 	                     (long) ((flags & DUK__IVAL_FLAG_ALLOW_CONST) ? 1 : 0),
67503 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_TEMP) ? 1 : 0),
67504 	                     (long) ((flags & DUK__IVAL_FLAG_REQUIRE_SHORT) ? 1 : 0)));
67505 
67506 	/* first coerce to a plain value */
67507 	duk__ivalue_toplain_raw(comp_ctx, x, forced_reg);
67508 	DUK_ASSERT(x->t == DUK_IVAL_PLAIN);
67509 
67510 	/* then to a register */
67511 	reg = duk__ispec_toregconst_raw(comp_ctx, &x->x1, forced_reg, flags);
67512 	duk__ivalue_regconst(x, reg);
67513 
67514 	return reg;
67515 }
67516 
67517 DUK_LOCAL duk_regconst_t duk__ivalue_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67518 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, 0 /*flags*/);
67519 }
67520 
67521 #if 0  /* unused */
67522 DUK_LOCAL duk_regconst_t duk__ivalue_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67523 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
67524 }
67525 #endif
67526 
67527 DUK_LOCAL void duk__ivalue_toforcedreg(duk_compiler_ctx *comp_ctx, duk_ivalue *x, duk_int_t forced_reg) {
67528 	DUK_ASSERT(forced_reg >= 0);
67529 	(void) duk__ivalue_toregconst_raw(comp_ctx, x, forced_reg, 0 /*flags*/);
67530 }
67531 
67532 DUK_LOCAL duk_regconst_t duk__ivalue_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67533 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
67534 }
67535 
67536 DUK_LOCAL duk_regconst_t duk__ivalue_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *x) {
67537 	return duk__ivalue_toregconst_raw(comp_ctx, x, -1, DUK__IVAL_FLAG_ALLOW_CONST | DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
67538 }
67539 
67540 /* The issues below can be solved with better flags */
67541 
67542 /* XXX: many operations actually want toforcedtemp() -- brand new temp? */
67543 /* XXX: need a toplain_ignore() which will only coerce a value to a temp
67544  * register if it might have a side effect.  Side-effect free values do not
67545  * need to be coerced.
67546  */
67547 
67548 /*
67549  *  Identifier handling
67550  */
67551 
67552 DUK_LOCAL duk_regconst_t duk__lookup_active_register_binding(duk_compiler_ctx *comp_ctx) {
67553 	duk_hthread *thr = comp_ctx->thr;
67554 	duk_hstring *h_varname;
67555 	duk_regconst_t ret;
67556 
67557 	DUK_DDD(DUK_DDDPRINT("resolving identifier reference to '%!T'",
67558 	                     (duk_tval *) duk_get_tval(thr, -1)));
67559 
67560 	/*
67561 	 *  Special name handling
67562 	 */
67563 
67564 	h_varname = duk_known_hstring(thr, -1);
67565 
67566 	if (h_varname == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)) {
67567 		DUK_DDD(DUK_DDDPRINT("flagging function as accessing 'arguments'"));
67568 		comp_ctx->curr_func.id_access_arguments = 1;
67569 	}
67570 
67571 	/*
67572 	 *  Inside one or more 'with' statements fall back to slow path always.
67573 	 *  (See e.g. test-stmt-with.js.)
67574 	 */
67575 
67576 	if (comp_ctx->curr_func.with_depth > 0) {
67577 		DUK_DDD(DUK_DDDPRINT("identifier lookup inside a 'with' -> fall back to slow path"));
67578 		goto slow_path_own;
67579 	}
67580 
67581 	/*
67582 	 *  Any catch bindings ("catch (e)") also affect identifier binding.
67583 	 *
67584 	 *  Currently, the varmap is modified for the duration of the catch
67585 	 *  clause to ensure any identifier accesses with the catch variable
67586 	 *  name will use slow path.
67587 	 */
67588 
67589 	duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
67590 	if (duk_is_number(thr, -1)) {
67591 		ret = duk_to_int(thr, -1);
67592 		duk_pop(thr);
67593 	} else {
67594 		duk_pop(thr);
67595 		if (comp_ctx->curr_func.catch_depth > 0 || comp_ctx->curr_func.with_depth > 0) {
67596 			DUK_DDD(DUK_DDDPRINT("slow path access from inside a try-catch or with needs _Varmap"));
67597 			goto slow_path_own;
67598 		} else {
67599 			/* In this case we're doing a variable lookup that doesn't
67600 			 * match our own variables, so _Varmap won't be needed at
67601 			 * run time.
67602 			 */
67603 			DUK_DDD(DUK_DDDPRINT("slow path access outside of try-catch and with, no need for _Varmap"));
67604 			goto slow_path_notown;
67605 		}
67606 	}
67607 
67608 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> reg %ld", (long) ret));
67609 	return ret;
67610 
67611  slow_path_notown:
67612 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, not own variable"));
67613 
67614 	comp_ctx->curr_func.id_access_slow = 1;
67615 	return (duk_regconst_t) -1;
67616 
67617  slow_path_own:
67618 	DUK_DDD(DUK_DDDPRINT("identifier lookup -> slow path, may be own variable"));
67619 
67620 	comp_ctx->curr_func.id_access_slow = 1;
67621 	comp_ctx->curr_func.id_access_slow_own = 1;
67622 	return (duk_regconst_t) -1;
67623 }
67624 
67625 /* Lookup an identifier name in the current varmap, indicating whether the
67626  * identifier is register-bound and if not, allocating a constant for the
67627  * identifier name.  Returns 1 if register-bound, 0 otherwise.  Caller can
67628  * also check (out_reg_varbind >= 0) to check whether or not identifier is
67629  * register bound.  The caller must NOT use out_rc_varname at all unless
67630  * return code is 0 or out_reg_varbind is < 0; this is becuase out_rc_varname
67631  * is unsigned and doesn't have a "unused" / none value.
67632  */
67633 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) {
67634 	duk_hthread *thr = comp_ctx->thr;
67635 	duk_regconst_t reg_varbind;
67636 	duk_regconst_t rc_varname;
67637 
67638 	/* [ ... varname ] */
67639 
67640 	duk_dup_top(thr);
67641 	reg_varbind = duk__lookup_active_register_binding(comp_ctx);
67642 
67643 	if (reg_varbind >= 0) {
67644 		*out_reg_varbind = reg_varbind;
67645 		*out_rc_varname = 0;  /* duk_regconst_t is unsigned, so use 0 as dummy value (ignored by caller) */
67646 		duk_pop(thr);
67647 		return 1;
67648 	} else {
67649 		rc_varname = duk__getconst(comp_ctx);
67650 		*out_reg_varbind = -1;
67651 		*out_rc_varname = rc_varname;
67652 		return 0;
67653 	}
67654 }
67655 
67656 /*
67657  *  Label handling
67658  *
67659  *  Labels are initially added with flags prohibiting both break and continue.
67660  *  When the statement type is finally uncovered (after potentially multiple
67661  *  labels), all the labels are updated to allow/prohibit break and continue.
67662  */
67663 
67664 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) {
67665 	duk_hthread *thr = comp_ctx->thr;
67666 	duk_size_t n;
67667 	duk_size_t new_size;
67668 	duk_uint8_t *p;
67669 	duk_labelinfo *li_start, *li;
67670 
67671 	/* Duplicate (shadowing) labels are not allowed, except for the empty
67672 	 * labels (which are used as default labels for switch and iteration
67673 	 * statements).
67674 	 *
67675 	 * We could also allow shadowing of non-empty pending labels without any
67676 	 * other issues than breaking the required label shadowing requirements
67677 	 * of the E5 specification, see Section 12.12.
67678 	 */
67679 
67680 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67681 	li_start = (duk_labelinfo *) (void *) p;
67682 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67683 	n = (duk_size_t) (li - li_start);
67684 
67685 	while (li > li_start) {
67686 		li--;
67687 
67688 		if (li->h_label == h_label && h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
67689 			DUK_ERROR_SYNTAX(thr, DUK_STR_DUPLICATE_LABEL);
67690 			DUK_WO_NORETURN(return;);
67691 		}
67692 	}
67693 
67694 	duk_push_hstring(thr, h_label);
67695 	DUK_ASSERT(n <= DUK_UARRIDX_MAX);  /* label limits */
67696 	(void) duk_put_prop_index(thr, comp_ctx->curr_func.labelnames_idx, (duk_uarridx_t) n);
67697 
67698 	new_size = (n + 1) * sizeof(duk_labelinfo);
67699 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, new_size);
67700 	/* XXX: slack handling, slow now */
67701 
67702 	/* relookup after possible realloc */
67703 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67704 	li_start = (duk_labelinfo *) (void *) p;
67705 	DUK_UNREF(li_start);  /* silence scan-build warning */
67706 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67707 	li--;
67708 
67709 	/* Labels can be used for iteration statements but also for other statements,
67710 	 * in particular a label can be used for a block statement.  All cases of a
67711 	 * named label accept a 'break' so that flag is set here.  Iteration statements
67712 	 * also allow 'continue', so that flag is updated when we figure out the
67713 	 * statement type.
67714 	 */
67715 
67716 	li->flags = DUK_LABEL_FLAG_ALLOW_BREAK;
67717 	li->label_id = label_id;
67718 	li->h_label = h_label;
67719 	li->catch_depth = comp_ctx->curr_func.catch_depth;   /* catch depth from current func */
67720 	li->pc_label = pc_label;
67721 
67722 	DUK_DDD(DUK_DDDPRINT("registered label: flags=0x%08lx, id=%ld, name=%!O, catch_depth=%ld, pc_label=%ld",
67723 	                     (unsigned long) li->flags, (long) li->label_id, (duk_heaphdr *) li->h_label,
67724 	                     (long) li->catch_depth, (long) li->pc_label));
67725 }
67726 
67727 /* Update all labels with matching label_id. */
67728 DUK_LOCAL void duk__update_label_flags(duk_compiler_ctx *comp_ctx, duk_int_t label_id, duk_small_uint_t flags) {
67729 	duk_uint8_t *p;
67730 	duk_labelinfo *li_start, *li;
67731 
67732 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(comp_ctx->thr->heap, comp_ctx->curr_func.h_labelinfos);
67733 	li_start = (duk_labelinfo *) (void *) p;
67734 	li = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67735 
67736 	/* Match labels starting from latest; once label_id no longer matches, we can
67737 	 * safely exit without checking the rest of the labels (only the topmost labels
67738 	 * are ever updated).
67739 	 */
67740 	while (li > li_start) {
67741 		li--;
67742 
67743 		if (li->label_id != label_id) {
67744 			break;
67745 		}
67746 
67747 		DUK_DDD(DUK_DDDPRINT("updating (overwriting) label flags for li=%p, label_id=%ld, flags=%ld",
67748 		                     (void *) li, (long) label_id, (long) flags));
67749 
67750 		li->flags = flags;
67751 	}
67752 }
67753 
67754 /* Lookup active label information.  Break/continue distinction is necessary to handle switch
67755  * statement related labels correctly: a switch will only catch a 'break', not a 'continue'.
67756  *
67757  * An explicit label cannot appear multiple times in the active set, but empty labels (unlabelled
67758  * iteration and switch statements) can.  A break will match the closest unlabelled or labelled
67759  * statement.  A continue will match the closest unlabelled or labelled iteration statement.  It is
67760  * a syntax error if a continue matches a labelled switch statement; because an explicit label cannot
67761  * be duplicated, the continue cannot match any valid label outside the switch.
67762  *
67763  * A side effect of these rules is that a LABEL statement related to a switch should never actually
67764  * catch a continue abrupt completion at run-time.  Hence an INVALID opcode can be placed in the
67765  * continue slot of the switch's LABEL statement.
67766  */
67767 
67768 /* XXX: awkward, especially the bunch of separate output values -> output struct? */
67769 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) {
67770 	duk_hthread *thr = comp_ctx->thr;
67771 	duk_uint8_t *p;
67772 	duk_labelinfo *li_start, *li_end, *li;
67773 	duk_bool_t match = 0;
67774 
67775 	DUK_DDD(DUK_DDDPRINT("looking up active label: label='%!O', is_break=%ld",
67776 	                     (duk_heaphdr *) h_label, (long) is_break));
67777 
67778 	DUK_UNREF(thr);
67779 
67780 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, comp_ctx->curr_func.h_labelinfos);
67781 	li_start = (duk_labelinfo *) (void *) p;
67782 	li_end = (duk_labelinfo *) (void *) (p + DUK_HBUFFER_GET_SIZE(comp_ctx->curr_func.h_labelinfos));
67783 	li = li_end;
67784 
67785 	/* Match labels starting from latest label because there can be duplicate empty
67786 	 * labels in the label set.
67787 	 */
67788 	while (li > li_start) {
67789 		li--;
67790 
67791 		if (li->h_label != h_label) {
67792 			DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] ->'%!O' != %!O",
67793 			                     (long) (li - li_start),
67794 			                     (duk_heaphdr *) li->h_label,
67795 			                     (duk_heaphdr *) h_label));
67796 			continue;
67797 		}
67798 
67799 		DUK_DDD(DUK_DDDPRINT("labelinfo[%ld] -> '%!O' label name matches (still need to check type)",
67800 		                     (long) (li - li_start), (duk_heaphdr *) h_label));
67801 
67802 		/* currently all labels accept a break, so no explicit check for it now */
67803 		DUK_ASSERT(li->flags & DUK_LABEL_FLAG_ALLOW_BREAK);
67804 
67805 		if (is_break) {
67806 			/* break matches always */
67807 			match = 1;
67808 			break;
67809 		} else if (li->flags & DUK_LABEL_FLAG_ALLOW_CONTINUE) {
67810 			/* iteration statements allow continue */
67811 			match = 1;
67812 			break;
67813 		} else {
67814 			/* continue matched this label -- we can only continue if this is the empty
67815 			 * label, for which duplication is allowed, and thus there is hope of
67816 			 * finding a match deeper in the label stack.
67817 			 */
67818 			if (h_label != DUK_HTHREAD_STRING_EMPTY_STRING(thr)) {
67819 				DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
67820 				DUK_WO_NORETURN(return;);
67821 			} else {
67822 				DUK_DDD(DUK_DDDPRINT("continue matched an empty label which does not "
67823 				                     "allow a continue -> continue lookup deeper in label stack"));
67824 			}
67825 		}
67826 	}
67827 	/* XXX: match flag is awkward, rework */
67828 	if (!match) {
67829 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LABEL);
67830 		DUK_WO_NORETURN(return;);
67831 	}
67832 
67833 	DUK_DDD(DUK_DDDPRINT("label match: %!O -> label_id %ld, catch_depth=%ld, pc_label=%ld",
67834 	                     (duk_heaphdr *) h_label, (long) li->label_id,
67835 	                     (long) li->catch_depth, (long) li->pc_label));
67836 
67837 	*out_label_id = li->label_id;
67838 	*out_label_catch_depth = li->catch_depth;
67839 	*out_label_pc = li->pc_label;
67840 	*out_is_closest = (li == li_end - 1);
67841 }
67842 
67843 DUK_LOCAL void duk__reset_labels_to_length(duk_compiler_ctx *comp_ctx, duk_size_t len) {
67844 	duk_hthread *thr = comp_ctx->thr;
67845 
67846 	duk_set_length(thr, comp_ctx->curr_func.labelnames_idx, len);
67847 	duk_hbuffer_resize(thr, comp_ctx->curr_func.h_labelinfos, sizeof(duk_labelinfo) * len);
67848 }
67849 
67850 /*
67851  *  Expression parsing: duk__expr_nud(), duk__expr_led(), duk__expr_lbp(), and helpers.
67852  *
67853  *  - duk__expr_nud(): ("null denotation"): process prev_token as a "start" of an expression (e.g. literal)
67854  *  - duk__expr_led(): ("left denotation"): process prev_token in the "middle" of an expression (e.g. operator)
67855  *  - duk__expr_lbp(): ("left-binding power"): return left-binding power of curr_token
67856  */
67857 
67858 /* object literal key tracking flags */
67859 #define DUK__OBJ_LIT_KEY_PLAIN  (1 << 0)  /* key encountered as a plain property */
67860 #define DUK__OBJ_LIT_KEY_GET    (1 << 1)  /* key encountered as a getter */
67861 #define DUK__OBJ_LIT_KEY_SET    (1 << 2)  /* key encountered as a setter */
67862 
67863 DUK_LOCAL void duk__nud_array_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
67864 	duk_hthread *thr = comp_ctx->thr;
67865 	duk_regconst_t reg_obj;                 /* result reg */
67866 	duk_regconst_t reg_temp;                /* temp reg */
67867 	duk_regconst_t temp_start;              /* temp reg value for start of loop */
67868 	duk_small_uint_t max_init_values;  /* max # of values initialized in one MPUTARR set */
67869 	duk_small_uint_t num_values;       /* number of values in current MPUTARR set */
67870 	duk_uarridx_t curr_idx;            /* current (next) array index */
67871 	duk_uarridx_t start_idx;           /* start array index of current MPUTARR set */
67872 	duk_uarridx_t init_idx;            /* last array index explicitly initialized, +1 */
67873 	duk_bool_t require_comma;          /* next loop requires a comma */
67874 #if !defined(DUK_USE_PREFER_SIZE)
67875 	duk_int_t pc_newarr;
67876 	duk_compiler_instr *instr;
67877 #endif
67878 
67879 	/* DUK_TOK_LBRACKET already eaten, current token is right after that */
67880 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LBRACKET);
67881 
67882 	max_init_values = DUK__MAX_ARRAY_INIT_VALUES;  /* XXX: depend on available temps? */
67883 
67884 	reg_obj = DUK__ALLOCTEMP(comp_ctx);
67885 #if !defined(DUK_USE_PREFER_SIZE)
67886 	pc_newarr = duk__get_current_pc(comp_ctx);
67887 #endif
67888 	duk__emit_bc(comp_ctx, DUK_OP_NEWARR, reg_obj);  /* XXX: patch initial size hint afterwards? */
67889 	temp_start = DUK__GETTEMP(comp_ctx);
67890 
67891 	/*
67892 	 *  Emit initializers in sets of maximum max_init_values.
67893 	 *  Corner cases such as single value initializers do not have
67894 	 *  special handling now.
67895 	 *
67896 	 *  Elided elements must not be emitted as 'undefined' values,
67897 	 *  because such values would be enumerable (which is incorrect).
67898 	 *  Also note that trailing elisions must be reflected in the
67899 	 *  length of the final array but cause no elements to be actually
67900 	 *  inserted.
67901 	 */
67902 
67903 	curr_idx = 0;
67904 	init_idx = 0;         /* tracks maximum initialized index + 1 */
67905 	start_idx = 0;
67906 	require_comma = 0;
67907 
67908 	for (;;) {
67909 		num_values = 0;
67910 		DUK__SETTEMP(comp_ctx, temp_start);
67911 
67912 		if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
67913 			break;
67914 		}
67915 
67916 		for (;;) {
67917 			if (comp_ctx->curr_token.t == DUK_TOK_RBRACKET) {
67918 				/* the outer loop will recheck and exit */
67919 				break;
67920 			}
67921 
67922 			/* comma check */
67923 			if (require_comma) {
67924 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
67925 					/* comma after a value, expected */
67926 					duk__advance(comp_ctx);
67927 					require_comma = 0;
67928 					continue;
67929 				} else {
67930 					goto syntax_error;
67931 				}
67932 			} else {
67933 				if (comp_ctx->curr_token.t == DUK_TOK_COMMA) {
67934 					/* elision - flush */
67935 					curr_idx++;
67936 					duk__advance(comp_ctx);
67937 					/* if num_values > 0, MPUTARR emitted by outer loop after break */
67938 					break;
67939 				}
67940 			}
67941 			/* else an array initializer element */
67942 
67943 			/* initial index */
67944 			if (num_values == 0) {
67945 				start_idx = curr_idx;
67946 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
67947 				duk__emit_load_int32(comp_ctx, reg_temp, (duk_int32_t) start_idx);
67948 			}
67949 
67950 			reg_temp = DUK__ALLOCTEMP(comp_ctx);   /* alloc temp just in case, to update max temp */
67951 			DUK__SETTEMP(comp_ctx, reg_temp);
67952 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);
67953 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
67954 
67955 			num_values++;
67956 			curr_idx++;
67957 			require_comma = 1;
67958 
67959 			if (num_values >= max_init_values) {
67960 				/* MPUTARR emitted by outer loop */
67961 				break;
67962 			}
67963 		}
67964 
67965 		if (num_values > 0) {
67966 			/* - A is a source register (it's not a write target, but used
67967 			 *   to identify the target object) but can be shuffled.
67968 			 * - B cannot be shuffled normally because it identifies a range
67969 			 *   of registers, the emitter has special handling for this
67970 			 *   (the "no shuffle" flag must not be set).
67971 			 * - C is a non-register number and cannot be shuffled, but
67972 			 *   never needs to be.
67973 			 */
67974 			duk__emit_a_b_c(comp_ctx,
67975 			                DUK_OP_MPUTARR |
67976 			                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
67977 			                    DUK__EMIT_FLAG_A_IS_SOURCE,
67978 			                reg_obj,
67979 			                temp_start,
67980 			                (duk_regconst_t) (num_values + 1));
67981 			init_idx = start_idx + num_values;
67982 
67983 			/* num_values and temp_start reset at top of outer loop */
67984 		}
67985 	}
67986 
67987 	/* Update initil size for NEWARR, doesn't need to be exact and is
67988 	 * capped at A field limit.
67989 	 */
67990 #if !defined(DUK_USE_PREFER_SIZE)
67991 	instr = duk__get_instr_ptr(comp_ctx, pc_newarr);
67992 	instr->ins |= DUK_ENC_OP_A(0, curr_idx > DUK_BC_A_MAX ? DUK_BC_A_MAX : curr_idx);
67993 #endif
67994 
67995 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RBRACKET);
67996 	duk__advance(comp_ctx);
67997 
67998 	DUK_DDD(DUK_DDDPRINT("array literal done, curridx=%ld, initidx=%ld",
67999 	                     (long) curr_idx, (long) init_idx));
68000 
68001 	/* trailing elisions? */
68002 	if (curr_idx > init_idx) {
68003 		/* yes, must set array length explicitly */
68004 		DUK_DDD(DUK_DDDPRINT("array literal has trailing elisions which affect its length"));
68005 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68006 		duk__emit_load_int32(comp_ctx, reg_temp, (duk_int_t) curr_idx);
68007 		duk__emit_a_bc(comp_ctx,
68008 		               DUK_OP_SETALEN | DUK__EMIT_FLAG_A_IS_SOURCE,
68009 		               reg_obj,
68010 		               reg_temp);
68011 	}
68012 
68013 	DUK__SETTEMP(comp_ctx, temp_start);
68014 
68015 	duk__ivalue_regconst(res, reg_obj);
68016 	return;
68017 
68018  syntax_error:
68019 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARRAY_LITERAL);
68020 	DUK_WO_NORETURN(return;);
68021 }
68022 
68023 typedef struct {
68024 	duk_regconst_t reg_obj;
68025 	duk_regconst_t temp_start;
68026 	duk_small_uint_t num_pairs;
68027 	duk_small_uint_t num_total_pairs;
68028 } duk__objlit_state;
68029 
68030 DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
68031 	if (st->num_pairs > 0) {
68032 		/* - A is a source register (it's not a write target, but used
68033 		 *   to identify the target object) but can be shuffled.
68034 		 * - B cannot be shuffled normally because it identifies a range
68035 		 *   of registers, the emitter has special handling for this
68036 		 *   (the "no shuffle" flag must not be set).
68037 		 * - C is a non-register number and cannot be shuffled, but
68038 		 *   never needs to be.
68039 		 */
68040 		DUK_ASSERT(st->num_pairs > 0);
68041 		duk__emit_a_b_c(comp_ctx,
68042 		                DUK_OP_MPUTOBJ |
68043 		                    DUK__EMIT_FLAG_NO_SHUFFLE_C |
68044 		                    DUK__EMIT_FLAG_A_IS_SOURCE,
68045 		                st->reg_obj,
68046 		                st->temp_start,
68047 		                (duk_regconst_t) (st->num_pairs * 2));
68048 		st->num_total_pairs += st->num_pairs;
68049 		st->num_pairs = 0;
68050 	}
68051 	DUK__SETTEMP(comp_ctx, st->temp_start);
68052 }
68053 
68054 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) {
68055 	if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t_nores == DUK_TOK_STRING) {
68056 		/* same handling for identifiers and strings */
68057 		DUK_ASSERT(tok->str1 != NULL);
68058 		duk_push_hstring(comp_ctx->thr, tok->str1);
68059 	} else if (tok->t == DUK_TOK_NUMBER) {
68060 		/* numbers can be loaded as numbers and coerced on the fly */
68061 		duk_push_number(comp_ctx->thr, tok->num);
68062 	} else {
68063 		return 1;  /* error */
68064 	}
68065 
68066 	duk__ivalue_plain_fromstack(comp_ctx, res);
68067 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68068 	duk__ivalue_toforcedreg(comp_ctx, res, reg_temp);
68069 	DUK__SETTEMP(comp_ctx, reg_temp + 1);
68070 	return 0;
68071 }
68072 
68073 DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68074 	duk_hthread *thr = comp_ctx->thr;
68075 	duk__objlit_state st;
68076 	duk_regconst_t reg_temp;          /* temp reg */
68077 	duk_small_uint_t max_init_pairs;  /* max # of key-value pairs initialized in one MPUTOBJ set */
68078 	duk_bool_t first;                 /* first value: comma must not precede the value */
68079 	duk_bool_t is_set, is_get;        /* temps */
68080 #if !defined(DUK_USE_PREFER_SIZE)
68081 	duk_int_t pc_newobj;
68082 	duk_compiler_instr *instr;
68083 #endif
68084 
68085 	DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
68086 
68087 	max_init_pairs = DUK__MAX_OBJECT_INIT_PAIRS;  /* XXX: depend on available temps? */
68088 
68089 	st.reg_obj = DUK__ALLOCTEMP(comp_ctx);    /* target object */
68090 	st.temp_start = DUK__GETTEMP(comp_ctx);   /* start of MPUTOBJ argument list */
68091 	st.num_pairs = 0;                         /* number of key/value pairs emitted for current MPUTOBJ set */
68092 	st.num_total_pairs = 0;                   /* number of key/value pairs emitted overall */
68093 
68094 #if !defined(DUK_USE_PREFER_SIZE)
68095 	pc_newobj = duk__get_current_pc(comp_ctx);
68096 #endif
68097 	duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
68098 
68099 	/*
68100 	 *  Emit initializers in sets of maximum max_init_pairs keys.
68101 	 *  Setter/getter is handled separately and terminates the
68102 	 *  current set of initializer values.  Corner cases such as
68103 	 *  single value initializers do not have special handling now.
68104 	 */
68105 
68106 	first = 1;
68107 	for (;;) {
68108 		/*
68109 		 *  ES5 and ES2015+ provide a lot of different PropertyDefinition
68110 		 *  formats, see http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer.
68111 		 *
68112 		 *  PropertyName can be IdentifierName (includes reserved words), a string
68113 		 *  literal, or a number literal.  Note that IdentifierName allows 'get' and
68114 		 *  'set' too, so we need to look ahead to the next token to distinguish:
68115 		 *
68116 		 *     { get : 1 }
68117 		 *
68118 		 *  and
68119 		 *
68120 		 *     { get foo() { return 1 } }
68121 		 *     { get get() { return 1 } }    // 'get' as getter propertyname
68122 		 *
68123 		 *  Finally, a trailing comma is allowed.
68124 		 *
68125 		 *  Key name is coerced to string at compile time (and ends up as a
68126 		 *  a string constant) even for numeric keys (e.g. "{1:'foo'}").
68127 		 *  These could be emitted using e.g. LDINT, but that seems hardly
68128 		 *  worth the effort and would increase code size.
68129 		 */
68130 
68131 		DUK_DDD(DUK_DDDPRINT("object literal loop, curr_token->t = %ld",
68132 		                     (long) comp_ctx->curr_token.t));
68133 
68134 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68135 			break;
68136 		}
68137 
68138 		if (first) {
68139 			first = 0;
68140 		} else {
68141 			if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
68142 				goto syntax_error;
68143 			}
68144 			duk__advance(comp_ctx);
68145 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
68146 				/* trailing comma followed by rcurly */
68147 				break;
68148 			}
68149 		}
68150 
68151 		/* Advance to get one step of lookup. */
68152 		duk__advance(comp_ctx);
68153 
68154 		/* Flush current MPUTOBJ if enough many pairs gathered. */
68155 		if (st.num_pairs >= max_init_pairs) {
68156 			duk__objlit_flush_keys(comp_ctx, &st);
68157 			DUK_ASSERT(st.num_pairs == 0);
68158 		}
68159 
68160 		/* Reset temp register state and reserve reg_temp and
68161 		 * reg_temp + 1 for handling the current property.
68162 		 */
68163 		DUK__SETTEMP(comp_ctx, st.temp_start + 2 * (duk_regconst_t) st.num_pairs);
68164 		reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68165 
68166 		/* NOTE: "get" and "set" are not officially ReservedWords and the lexer
68167 		 * currently treats them always like ordinary identifiers (DUK_TOK_GET
68168 		 * and DUK_TOK_SET are unused).  They need to be detected based on the
68169 		 * identifier string content.
68170 		 */
68171 
68172 		is_get = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68173 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_GET(thr));
68174 		is_set = (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68175 		          comp_ctx->prev_token.str1 == DUK_HTHREAD_STRING_SET(thr));
68176 		if ((is_get || is_set) && comp_ctx->curr_token.t != DUK_TOK_COLON) {
68177 			/* getter/setter */
68178 			duk_int_t fnum;
68179 
68180 			duk__objlit_flush_keys(comp_ctx, &st);
68181 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);  /* 2 regs are guaranteed to be allocated w.r.t. temp_max */
68182 			reg_temp = DUK__ALLOCTEMPS(comp_ctx, 2);
68183 
68184 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->curr_token, reg_temp) != 0) {
68185 				goto syntax_error;
68186 			}
68187 
68188 			/* curr_token = get/set name */
68189 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_GETSET);
68190 
68191 			duk__emit_a_bc(comp_ctx,
68192 			               DUK_OP_CLOSURE,
68193 			               st.temp_start + 1,
68194 			               (duk_regconst_t) fnum);
68195 
68196 			/* Slot C is used in a non-standard fashion (range of regs),
68197 			 * emitter code has special handling for it (must not set the
68198 			 * "no shuffle" flag).
68199 			 */
68200 			duk__emit_a_bc(comp_ctx,
68201 			              (is_get ? DUK_OP_INITGET : DUK_OP_INITSET) | DUK__EMIT_FLAG_A_IS_SOURCE,
68202 			              st.reg_obj,
68203 			              st.temp_start);   /* temp_start+0 = key, temp_start+1 = closure */
68204 
68205 			DUK_ASSERT(st.num_pairs == 0);  /* temp state is reset on next loop */
68206 #if defined(DUK_USE_ES6)
68207 		} else if (comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
68208 		           (comp_ctx->curr_token.t == DUK_TOK_COMMA || comp_ctx->curr_token.t == DUK_TOK_RCURLY)) {
68209 			duk_bool_t load_rc;
68210 
68211 			load_rc = duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp);
68212 			DUK_UNREF(load_rc);
68213 			DUK_ASSERT(load_rc == 0);  /* always succeeds because token is identifier */
68214 
68215 			duk__ivalue_var_hstring(comp_ctx, res, comp_ctx->prev_token.str1);
68216 			DUK_ASSERT(DUK__GETTEMP(comp_ctx) == reg_temp + 1);
68217 			duk__ivalue_toforcedreg(comp_ctx, res, reg_temp + 1);
68218 
68219 			st.num_pairs++;
68220 		} else if ((comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER ||
68221 		            comp_ctx->prev_token.t == DUK_TOK_STRING ||
68222 		            comp_ctx->prev_token.t == DUK_TOK_NUMBER) &&
68223 		           comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
68224 			duk_int_t fnum;
68225 
68226 			/* Parsing-wise there's a small hickup here: the token parsing
68227 			 * state is one step too advanced for the function parse helper
68228 			 * compared to other cases.  The current solution is an extra
68229 			 * flag to indicate whether function parsing should use the
68230 			 * current or the previous token to starting parsing from.
68231 			 */
68232 
68233 			if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68234 				goto syntax_error;
68235 			}
68236 
68237 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_USE_PREVTOKEN | DUK__FUNC_FLAG_METDEF);
68238 
68239 			duk__emit_a_bc(comp_ctx,
68240 			               DUK_OP_CLOSURE,
68241 			               reg_temp + 1,
68242 			               (duk_regconst_t) fnum);
68243 
68244 			st.num_pairs++;
68245 #endif  /* DUK_USE_ES6 */
68246 		} else {
68247 #if defined(DUK_USE_ES6)
68248 			if (comp_ctx->prev_token.t == DUK_TOK_LBRACKET) {
68249 				/* ES2015 computed property name.  Executor ToPropertyKey()
68250 				 * coerces the key at runtime.
68251 				 */
68252 				DUK__SETTEMP(comp_ctx, reg_temp);
68253 				duk__expr_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR, reg_temp);
68254 				duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
68255 
68256 				/* XXX: If next token is '(' we're dealing with
68257 				 * the method shorthand with a computed name,
68258 				 * e.g. { [Symbol.for('foo')](a,b) {} }.  This
68259 				 * form is not yet supported and causes a
68260 				 * SyntaxError on the DUK_TOK_COLON check below.
68261 				 */
68262 			}
68263 			else
68264 #endif  /* DUK_USE_ES6 */
68265 			{
68266 				if (duk__objlit_load_key(comp_ctx, res, &comp_ctx->prev_token, reg_temp) != 0) {
68267 					goto syntax_error;
68268 				}
68269 			}
68270 
68271 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
68272 
68273 			DUK__SETTEMP(comp_ctx, reg_temp + 1);
68274 			duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp + 1 /*forced_reg*/);
68275 
68276 			st.num_pairs++;
68277 		}
68278 	}  /* property loop */
68279 
68280 	/* Flush remaining properties. */
68281 	duk__objlit_flush_keys(comp_ctx, &st);
68282 	DUK_ASSERT(st.num_pairs == 0);
68283 	DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
68284 
68285 	/* Update initial size for NEWOBJ.  The init size doesn't need to be
68286 	 * exact as the purpose is just to avoid object resizes in common
68287 	 * cases.  The size is capped to field A limit, and will be too high
68288 	 * if the object literal contains duplicate keys (this is harmless but
68289 	 * increases memory traffic if the object is compacted later on).
68290 	 */
68291 #if !defined(DUK_USE_PREFER_SIZE)
68292 	instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
68293 	instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > DUK_BC_A_MAX ? DUK_BC_A_MAX : st.num_total_pairs);
68294 #endif
68295 
68296 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
68297 	duk__advance(comp_ctx);  /* No RegExp after object literal. */
68298 
68299 	duk__ivalue_regconst(res, st.reg_obj);
68300 	return;
68301 
68302  syntax_error:
68303 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_OBJECT_LITERAL);
68304 	DUK_WO_NORETURN(return;);
68305 }
68306 
68307 /* Parse argument list.  Arguments are written to temps starting from
68308  * "next temp".  Returns number of arguments parsed.  Expects left paren
68309  * to be already eaten, and eats the right paren before returning.
68310  */
68311 DUK_LOCAL duk_int_t duk__parse_arguments(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68312 	duk_int_t nargs = 0;
68313 	duk_regconst_t reg_temp;
68314 
68315 	/* Note: expect that caller has already eaten the left paren */
68316 
68317 	DUK_DDD(DUK_DDDPRINT("start parsing arguments, prev_token.t=%ld, curr_token.t=%ld",
68318 	                     (long) comp_ctx->prev_token.t, (long) comp_ctx->curr_token.t));
68319 
68320 	for (;;) {
68321 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
68322 			break;
68323 		}
68324 		if (nargs > 0) {
68325 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
68326 		}
68327 
68328 		/* We want the argument expression value to go to "next temp"
68329 		 * without additional moves.  That should almost always be the
68330 		 * case, but we double check after expression parsing.
68331 		 *
68332 		 * This is not the cleanest possible approach.
68333 		 */
68334 
68335 		reg_temp = DUK__ALLOCTEMP(comp_ctx);  /* bump up "allocated" reg count, just in case */
68336 		DUK__SETTEMP(comp_ctx, reg_temp);
68337 
68338 		/* binding power must be high enough to NOT allow comma expressions directly */
68339 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp);  /* always allow 'in', coerce to 'tr' just in case */
68340 
68341 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
68342 		nargs++;
68343 
68344 		DUK_DDD(DUK_DDDPRINT("argument #%ld written into reg %ld", (long) nargs, (long) reg_temp));
68345 	}
68346 
68347 	/* eat the right paren */
68348 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
68349 
68350 	DUK_DDD(DUK_DDDPRINT("end parsing arguments"));
68351 
68352 	return nargs;
68353 }
68354 
68355 DUK_LOCAL duk_bool_t duk__expr_is_empty(duk_compiler_ctx *comp_ctx) {
68356 	/* empty expressions can be detected conveniently with nud/led counts */
68357 	return (comp_ctx->curr_func.nud_count == 0) &&
68358 	       (comp_ctx->curr_func.led_count == 0);
68359 }
68360 
68361 DUK_LOCAL void duk__expr_nud(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
68362 	duk_hthread *thr = comp_ctx->thr;
68363 	duk_token *tk;
68364 	duk_regconst_t temp_at_entry;
68365 	duk_small_uint_t tok;
68366 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
68367 
68368 	/*
68369 	 *  ctx->prev_token     token to process with duk__expr_nud()
68370 	 *  ctx->curr_token     updated by caller
68371 	 *
68372 	 *  Note: the token in the switch below has already been eaten.
68373 	 */
68374 
68375 	temp_at_entry = DUK__GETTEMP(comp_ctx);
68376 
68377 	comp_ctx->curr_func.nud_count++;
68378 
68379 	tk = &comp_ctx->prev_token;
68380 	tok = tk->t;
68381 	res->t = DUK_IVAL_NONE;
68382 
68383 	DUK_DDD(DUK_DDDPRINT("duk__expr_nud(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
68384 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
68385 
68386 	switch (tok) {
68387 
68388 	/* PRIMARY EXPRESSIONS */
68389 
68390 	case DUK_TOK_THIS: {
68391 		duk_regconst_t reg_temp;
68392 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68393 		duk__emit_bc(comp_ctx,
68394 		             DUK_OP_LDTHIS,
68395 		             reg_temp);
68396 		duk__ivalue_regconst(res, reg_temp);
68397 		return;
68398 	}
68399 	case DUK_TOK_IDENTIFIER: {
68400 		duk__ivalue_var_hstring(comp_ctx, res, tk->str1);
68401 		return;
68402 	}
68403 	case DUK_TOK_NULL: {
68404 		duk_push_null(thr);
68405 		goto plain_value;
68406 	}
68407 	case DUK_TOK_TRUE: {
68408 		duk_push_true(thr);
68409 		goto plain_value;
68410 	}
68411 	case DUK_TOK_FALSE: {
68412 		duk_push_false(thr);
68413 		goto plain_value;
68414 	}
68415 	case DUK_TOK_NUMBER: {
68416 		duk_push_number(thr, tk->num);
68417 		goto plain_value;
68418 	}
68419 	case DUK_TOK_STRING: {
68420 		DUK_ASSERT(tk->str1 != NULL);
68421 		duk_push_hstring(thr, tk->str1);
68422 		goto plain_value;
68423 	}
68424 	case DUK_TOK_REGEXP: {
68425 #if defined(DUK_USE_REGEXP_SUPPORT)
68426 		duk_regconst_t reg_temp;
68427 		duk_regconst_t rc_re_bytecode;  /* const */
68428 		duk_regconst_t rc_re_source;    /* const */
68429 
68430 		DUK_ASSERT(tk->str1 != NULL);
68431 		DUK_ASSERT(tk->str2 != NULL);
68432 
68433 		DUK_DDD(DUK_DDDPRINT("emitting regexp op, str1=%!O, str2=%!O",
68434 		                     (duk_heaphdr *) tk->str1,
68435 		                     (duk_heaphdr *) tk->str2));
68436 
68437 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68438 		duk_push_hstring(thr, tk->str1);
68439 		duk_push_hstring(thr, tk->str2);
68440 
68441 		/* [ ... pattern flags ] */
68442 
68443 		duk_regexp_compile(thr);
68444 
68445 		/* [ ... escaped_source bytecode ] */
68446 
68447 		rc_re_bytecode = duk__getconst(comp_ctx);
68448 		rc_re_source = duk__getconst(comp_ctx);
68449 
68450 		duk__emit_a_b_c(comp_ctx,
68451 		                DUK_OP_REGEXP | DUK__EMIT_FLAG_BC_REGCONST,
68452 		                reg_temp /*a*/,
68453 		                rc_re_bytecode /*b*/,
68454 		                rc_re_source /*c*/);
68455 
68456 		duk__ivalue_regconst(res, reg_temp);
68457 		return;
68458 #else  /* DUK_USE_REGEXP_SUPPORT */
68459 		goto syntax_error;
68460 #endif  /* DUK_USE_REGEXP_SUPPORT */
68461 	}
68462 	case DUK_TOK_LBRACKET: {
68463 		DUK_DDD(DUK_DDDPRINT("parsing array literal"));
68464 		duk__nud_array_literal(comp_ctx, res);
68465 		return;
68466 	}
68467 	case DUK_TOK_LCURLY: {
68468 		DUK_DDD(DUK_DDDPRINT("parsing object literal"));
68469 		duk__nud_object_literal(comp_ctx, res);
68470 		return;
68471 	}
68472 	case DUK_TOK_LPAREN: {
68473 		duk_bool_t prev_allow_in;
68474 
68475 		comp_ctx->curr_func.paren_level++;
68476 		prev_allow_in = comp_ctx->curr_func.allow_in;
68477 		comp_ctx->curr_func.allow_in = 1; /* reset 'allow_in' for parenthesized expression */
68478 
68479 		duk__expr(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, terminates at a ')' */
68480 
68481 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* No RegExp after parenthesized expression. */
68482 		comp_ctx->curr_func.allow_in = prev_allow_in;
68483 		comp_ctx->curr_func.paren_level--;
68484 		return;
68485 	}
68486 
68487 	/* MEMBER/NEW/CALL EXPRESSIONS */
68488 
68489 	case DUK_TOK_NEW: {
68490 		/*
68491 		 *  Parsing an expression starting with 'new' is tricky because
68492 		 *  there are multiple possible productions deriving from
68493 		 *  LeftHandSideExpression which begin with 'new'.
68494 		 *
68495 		 *  We currently resort to one-token lookahead to distinguish the
68496 		 *  cases.  Hopefully this is correct.  The binding power must be
68497 		 *  such that parsing ends at an LPAREN (CallExpression) but not at
68498 		 *  a PERIOD or LBRACKET (MemberExpression).
68499 		 *
68500 		 *  See doc/compiler.rst for discussion on the parsing approach,
68501 		 *  and testcases/test-dev-new.js for a bunch of documented tests.
68502 		 */
68503 
68504 		duk_regconst_t reg_target;
68505 		duk_int_t nargs;
68506 
68507 		DUK_DDD(DUK_DDDPRINT("begin parsing new expression"));
68508 
68509 		reg_target = DUK__ALLOCTEMPS(comp_ctx, 2);
68510 
68511 #if defined(DUK_USE_ES6)
68512 		if (comp_ctx->curr_token.t == DUK_TOK_PERIOD) {
68513 			/* new.target */
68514 			DUK_DDD(DUK_DDDPRINT("new.target"));
68515 			duk__advance(comp_ctx);
68516 			if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER ||
68517 			    !duk_hstring_equals_ascii_cstring(comp_ctx->curr_token.str1, "target")) {
68518 				goto syntax_error_newtarget;
68519 			}
68520 			if (comp_ctx->curr_func.is_global) {
68521 				goto syntax_error_newtarget;
68522 			}
68523 			duk__advance(comp_ctx);
68524 			duk__emit_bc(comp_ctx,
68525 			             DUK_OP_NEWTARGET,
68526 			             reg_target);
68527 			duk__ivalue_regconst(res, reg_target);
68528 			return;
68529 		}
68530 #endif  /* DUK_USE_ES6 */
68531 
68532 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_CALL /*rbp_flags*/, reg_target /*forced_reg*/);
68533 		duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, reg_target + 1);  /* default instance */
68534 		DUK__SETTEMP(comp_ctx, reg_target + 2);
68535 
68536 		/* XXX: 'new obj.noSuch()' doesn't use GETPROPC now which
68537 		 * makes the error message worse than for obj.noSuch().
68538 		 */
68539 
68540 		if (comp_ctx->curr_token.t == DUK_TOK_LPAREN) {
68541 			/* 'new' MemberExpression Arguments */
68542 			DUK_DDD(DUK_DDDPRINT("new expression has argument list"));
68543 			duk__advance(comp_ctx);
68544 			nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp", reg_target + 1 */
68545 			/* right paren eaten */
68546 		} else {
68547 			/* 'new' MemberExpression */
68548 			DUK_DDD(DUK_DDDPRINT("new expression has no argument list"));
68549 			nargs = 0;
68550 		}
68551 
68552 		duk__emit_a_bc(comp_ctx,
68553 		              DUK_OP_CALL0 | DUK_BC_CALL_FLAG_CONSTRUCT,
68554 		              nargs /*num_args*/,
68555 		              reg_target /*target*/);
68556 
68557 		DUK_DDD(DUK_DDDPRINT("end parsing new expression"));
68558 
68559 		duk__ivalue_regconst(res, reg_target);
68560 		return;
68561 	}
68562 
68563 	/* FUNCTION EXPRESSIONS */
68564 
68565 	case DUK_TOK_FUNCTION: {
68566 		/* Function expression.  Note that any statement beginning with 'function'
68567 		 * is handled by the statement parser as a function declaration, or a
68568 		 * non-standard function expression/statement (or a SyntaxError).  We only
68569 		 * handle actual function expressions (occurring inside an expression) here.
68570 		 *
68571 		 * O(depth^2) parse count for inner functions is handled by recording a
68572 		 * lexer offset on the first compilation pass, so that the function can
68573 		 * be efficiently skipped on the second pass.  This is encapsulated into
68574 		 * duk__parse_func_like_fnum().
68575 		 */
68576 
68577 		duk_regconst_t reg_temp;
68578 		duk_int_t fnum;
68579 
68580 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
68581 
68582 		/* curr_token follows 'function' */
68583 		fnum = duk__parse_func_like_fnum(comp_ctx, 0 /*flags*/);
68584 		DUK_DDD(DUK_DDDPRINT("parsed inner function -> fnum %ld", (long) fnum));
68585 
68586 		duk__emit_a_bc(comp_ctx,
68587 		               DUK_OP_CLOSURE,
68588 		               reg_temp /*a*/,
68589 		               (duk_regconst_t) fnum /*bc*/);
68590 
68591 		duk__ivalue_regconst(res, reg_temp);
68592 		return;
68593 	}
68594 
68595 	/* UNARY EXPRESSIONS */
68596 
68597 	case DUK_TOK_DELETE: {
68598 		/* Delete semantics are a bit tricky.  The description in E5 specification
68599 		 * is kind of confusing, because it distinguishes between resolvability of
68600 		 * a reference (which is only known at runtime) seemingly at compile time
68601 		 * (= SyntaxError throwing).
68602 		 */
68603 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68604 		if (res->t == DUK_IVAL_VAR) {
68605 			/* not allowed in strict mode, regardless of whether resolves;
68606 			 * in non-strict mode DELVAR handles both non-resolving and
68607 			 * resolving cases (the specification description is a bit confusing).
68608 			 */
68609 
68610 			duk_regconst_t reg_temp;
68611 			duk_regconst_t reg_varbind;
68612 			duk_regconst_t rc_varname;
68613 
68614 			if (comp_ctx->curr_func.is_strict) {
68615 				DUK_ERROR_SYNTAX(thr, DUK_STR_CANNOT_DELETE_IDENTIFIER);
68616 				DUK_WO_NORETURN(return;);
68617 			}
68618 
68619 			DUK__SETTEMP(comp_ctx, temp_at_entry);
68620 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
68621 
68622 			duk_dup(thr, res->x1.valstack_idx);
68623 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68624 				/* register bound variables are non-configurable -> always false */
68625 				duk__emit_bc(comp_ctx,
68626 				             DUK_OP_LDFALSE,
68627 				             reg_temp);
68628 			} else {
68629 				duk_dup(thr, res->x1.valstack_idx);
68630 				rc_varname = duk__getconst(comp_ctx);
68631 				duk__emit_a_bc(comp_ctx,
68632 				               DUK_OP_DELVAR,
68633 				               reg_temp,
68634 				               rc_varname);
68635 			}
68636 			duk__ivalue_regconst(res, reg_temp);
68637 		} else if (res->t == DUK_IVAL_PROP) {
68638 			duk_regconst_t reg_temp;
68639 			duk_regconst_t reg_obj;
68640 			duk_regconst_t rc_key;
68641 
68642 			DUK__SETTEMP(comp_ctx, temp_at_entry);
68643 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
68644 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
68645 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
68646 			duk__emit_a_b_c(comp_ctx,
68647 			                DUK_OP_DELPROP | DUK__EMIT_FLAG_BC_REGCONST,
68648 			                reg_temp,
68649 			                reg_obj,
68650 			                rc_key);
68651 
68652 			duk__ivalue_regconst(res, reg_temp);
68653 		} else {
68654 			/* non-Reference deletion is always 'true', even in strict mode */
68655 			duk_push_true(thr);
68656 			goto plain_value;
68657 		}
68658 		return;
68659 	}
68660 	case DUK_TOK_VOID: {
68661 		duk__expr_toplain_ignore(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68662 		duk_push_undefined(thr);
68663 		goto plain_value;
68664 	}
68665 	case DUK_TOK_TYPEOF: {
68666 		/* 'typeof' must handle unresolvable references without throwing
68667 		 * a ReferenceError (E5 Section 11.4.3).  Register mapped values
68668 		 * will never be unresolvable so special handling is only required
68669 		 * when an identifier is a "slow path" one.
68670 		 */
68671 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68672 
68673 		if (res->t == DUK_IVAL_VAR) {
68674 			duk_regconst_t reg_varbind;
68675 			duk_regconst_t rc_varname;
68676 			duk_regconst_t reg_temp;
68677 
68678 			duk_dup(thr, res->x1.valstack_idx);
68679 			if (!duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68680 				DUK_DDD(DUK_DDDPRINT("typeof for an identifier name which could not be resolved "
68681 				                     "at compile time, need to use special run-time handling"));
68682 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
68683 				duk__emit_a_bc(comp_ctx,
68684 				               DUK_OP_TYPEOFID,
68685 				               reg_temp,
68686 				               rc_varname);
68687 				duk__ivalue_regconst(res, reg_temp);
68688 				return;
68689 			}
68690 		}
68691 
68692 		args = DUK_OP_TYPEOF;
68693 		goto unary;
68694 	}
68695 	case DUK_TOK_INCREMENT: {
68696 		args = (DUK_OP_PREINCP << 8) + DUK_OP_PREINCR;
68697 		goto preincdec;
68698 	}
68699 	case DUK_TOK_DECREMENT: {
68700 		args = (DUK_OP_PREDECP << 8) + DUK_OP_PREDECR;
68701 		goto preincdec;
68702 	}
68703 	case DUK_TOK_ADD: {
68704 		/* unary plus */
68705 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68706 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
68707 		    duk_is_number(thr, res->x1.valstack_idx)) {
68708 			/* unary plus of a number is identity */
68709 			return;
68710 		}
68711 		args = DUK_OP_UNP;
68712 		goto unary;
68713 	}
68714 	case DUK_TOK_SUB: {
68715 		/* unary minus */
68716 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68717 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE &&
68718 		    duk_is_number(thr, res->x1.valstack_idx)) {
68719 			/* this optimization is important to handle negative literals
68720 			 * (which are not directly provided by the lexical grammar)
68721 			 */
68722 			duk_tval *tv_num;
68723 			duk_double_union du;
68724 
68725 			tv_num = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
68726 			DUK_ASSERT(tv_num != NULL);
68727 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_num));
68728 			du.d = DUK_TVAL_GET_NUMBER(tv_num);
68729 			du.d = -du.d;
68730 			DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
68731 			DUK_TVAL_SET_NUMBER(tv_num, du.d);
68732 			return;
68733 		}
68734 		args = DUK_OP_UNM;
68735 		goto unary;
68736 	}
68737 	case DUK_TOK_BNOT: {
68738 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68739 		args = DUK_OP_BNOT;
68740 		goto unary;
68741 	}
68742 	case DUK_TOK_LNOT: {
68743 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68744 		if (res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_VALUE) {
68745 			/* Very minimal inlining to handle common idioms '!0' and '!1',
68746 			 * and also boolean arguments like '!false' and '!true'.
68747 			 */
68748 			duk_tval *tv_val;
68749 
68750 			tv_val = DUK_GET_TVAL_POSIDX(thr, res->x1.valstack_idx);
68751 			DUK_ASSERT(tv_val != NULL);
68752 			if (DUK_TVAL_IS_NUMBER(tv_val)) {
68753 				duk_double_t d;
68754 				d = DUK_TVAL_GET_NUMBER(tv_val);
68755 				if (d == 0.0) {
68756 					/* Matches both +0 and -0 on purpose. */
68757 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !0 -> true"));
68758 					DUK_TVAL_SET_BOOLEAN_TRUE(tv_val);
68759 					return;
68760 				} else if (d == 1.0) {
68761 					DUK_DDD(DUK_DDDPRINT("inlined lnot: !1 -> false"));
68762 					DUK_TVAL_SET_BOOLEAN_FALSE(tv_val);
68763 					return;
68764 				}
68765 			} else if (DUK_TVAL_IS_BOOLEAN(tv_val)) {
68766 				duk_small_uint_t v;
68767 				v = DUK_TVAL_GET_BOOLEAN(tv_val);
68768 				DUK_DDD(DUK_DDDPRINT("inlined lnot boolean: %ld", (long) v));
68769 				DUK_ASSERT(v == 0 || v == 1);
68770 				DUK_TVAL_SET_BOOLEAN(tv_val, v ^ 0x01);
68771 				return;
68772 			}
68773 		}
68774 		args = DUK_OP_LNOT;
68775 		goto unary;
68776 	}
68777 
68778 	}  /* end switch */
68779 
68780 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
68781 	DUK_WO_NORETURN(return;);
68782 
68783  unary:
68784 	{
68785 		/* Unary opcodes use just the 'BC' register source because it
68786 		 * matches current shuffle limits, and maps cleanly to 16 high
68787 		 * bits of the opcode.
68788 		 */
68789 
68790 		duk_regconst_t reg_src, reg_res;
68791 
68792 		reg_src = duk__ivalue_toregconst_raw(comp_ctx, res, -1 /*forced_reg*/, 0 /*flags*/);
68793 		if (DUK__ISREG_TEMP(comp_ctx, reg_src)) {
68794 			reg_res = reg_src;
68795 		} else {
68796 			reg_res = DUK__ALLOCTEMP(comp_ctx);
68797 		}
68798 		duk__emit_a_bc(comp_ctx,
68799 		             args,
68800 		             reg_res,
68801 		             reg_src);
68802 		duk__ivalue_regconst(res, reg_res);
68803 		return;
68804 	}
68805 
68806  preincdec:
68807 	{
68808 		/* preincrement and predecrement */
68809 		duk_regconst_t reg_res;
68810 		duk_small_uint_t args_op1 = args & 0xff;  /* DUK_OP_PREINCR/DUK_OP_PREDECR */
68811 		duk_small_uint_t args_op2 = args >> 8;    /* DUK_OP_PREINCP_RR/DUK_OP_PREDECP_RR */
68812 
68813 		/* Specific assumptions for opcode numbering. */
68814 		DUK_ASSERT(DUK_OP_PREINCR + 4 == DUK_OP_PREINCV);
68815 		DUK_ASSERT(DUK_OP_PREDECR + 4 == DUK_OP_PREDECV);
68816 
68817 		reg_res = DUK__ALLOCTEMP(comp_ctx);
68818 
68819 		duk__expr(comp_ctx, res, DUK__BP_MULTIPLICATIVE /*rbp_flags*/);  /* UnaryExpression */
68820 		if (res->t == DUK_IVAL_VAR) {
68821 			duk_hstring *h_varname;
68822 			duk_regconst_t reg_varbind;
68823 			duk_regconst_t rc_varname;
68824 
68825 			h_varname = duk_known_hstring(thr, res->x1.valstack_idx);
68826 
68827 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
68828 				goto syntax_error;
68829 			}
68830 
68831 			duk_dup(thr, res->x1.valstack_idx);
68832 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
68833 				duk__emit_a_bc(comp_ctx,
68834 				               args_op1,  /* e.g. DUK_OP_PREINCR */
68835 				               reg_res,
68836 				               reg_varbind);
68837 			} else {
68838 				duk__emit_a_bc(comp_ctx,
68839 				                args_op1 + 4,  /* e.g. DUK_OP_PREINCV */
68840 				                reg_res,
68841 				                rc_varname);
68842 			}
68843 
68844 			DUK_DDD(DUK_DDDPRINT("preincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
68845 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
68846 		} else if (res->t == DUK_IVAL_PROP) {
68847 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
68848 			duk_regconst_t rc_key;
68849 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
68850 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
68851 			duk__emit_a_b_c(comp_ctx,
68852 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_PREINCP */
68853 			                reg_res,
68854 			                reg_obj,
68855 			                rc_key);
68856 		} else {
68857 			/* Technically return value is not needed because INVLHS will
68858 			 * unconditially throw a ReferenceError.  Coercion is necessary
68859 			 * for proper semantics (consider ToNumber() called for an object).
68860 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
68861 			 */
68862 
68863 			duk__ivalue_toforcedreg(comp_ctx, res, reg_res);
68864 			duk__emit_bc(comp_ctx,
68865 			             DUK_OP_UNP,
68866 			             reg_res);  /* for side effects, result ignored */
68867 			duk__emit_op_only(comp_ctx,
68868 			                  DUK_OP_INVLHS);
68869 		}
68870 		DUK__SETTEMP(comp_ctx, reg_res + 1);
68871 		duk__ivalue_regconst(res, reg_res);
68872 		return;
68873 	}
68874 
68875  plain_value:
68876 	{
68877 		/* Stack top contains plain value */
68878 		duk__ivalue_plain_fromstack(comp_ctx, res);
68879 		return;
68880 	}
68881 
68882 #if defined(DUK_USE_ES6)
68883  syntax_error_newtarget:
68884 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_NEWTARGET);
68885 	DUK_WO_NORETURN(return;);
68886 #endif
68887 
68888  syntax_error:
68889 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
68890 	DUK_WO_NORETURN(return;);
68891 }
68892 
68893 /* XXX: add flag to indicate whether caller cares about return value; this
68894  * affects e.g. handling of assignment expressions.  This change needs API
68895  * changes elsewhere too.
68896  */
68897 DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
68898 	duk_hthread *thr = comp_ctx->thr;
68899 	duk_token *tk;
68900 	duk_small_uint_t tok;
68901 	duk_uint32_t args;  /* temp variable to pass constants and flags to shared code */
68902 
68903 	/*
68904 	 *  ctx->prev_token     token to process with duk__expr_led()
68905 	 *  ctx->curr_token     updated by caller
68906 	 */
68907 
68908 	comp_ctx->curr_func.led_count++;
68909 
68910 	/* The token in the switch has already been eaten here */
68911 	tk = &comp_ctx->prev_token;
68912 	tok = tk->t;
68913 
68914 	DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
68915 	                     (long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));
68916 
68917 	/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */
68918 
68919 	switch (tok) {
68920 
68921 	/* PRIMARY EXPRESSIONS */
68922 
68923 	case DUK_TOK_PERIOD: {
68924 		/* Property access expressions are critical for correct LHS ordering,
68925 		 * see comments in duk__expr()!
68926 		 *
68927 		 * A conservative approach would be to use duk__ivalue_totempconst()
68928 		 * for 'left'.  However, allowing a reg-bound variable seems safe here
68929 		 * and is nice because "foo.bar" is a common expression.  If the ivalue
68930 		 * is used in an expression a GETPROP will occur before any changes to
68931 		 * the base value can occur.  If the ivalue is used as an assignment
68932 		 * LHS, the assignment code will ensure the base value is safe from
68933 		 * RHS mutation.
68934 		 */
68935 
68936 		/* XXX: This now coerces an identifier into a GETVAR to a temp, which
68937 		 * causes an extra LDREG in call setup.  It's sufficient to coerce to a
68938 		 * unary ivalue?
68939 		 */
68940 		duk__ivalue_toplain(comp_ctx, left);
68941 
68942 		/* NB: must accept reserved words as property name */
68943 		if (comp_ctx->curr_token.t_nores != DUK_TOK_IDENTIFIER) {
68944 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
68945 			DUK_WO_NORETURN(return;);
68946 		}
68947 
68948 		res->t = DUK_IVAL_PROP;
68949 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
68950 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
68951 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
68952 		duk_replace(thr, res->x2.valstack_idx);
68953 		res->x2.t = DUK_ISPEC_VALUE;
68954 
68955 		/* special RegExp literal handling after IdentifierName */
68956 		comp_ctx->curr_func.reject_regexp_in_adv = 1;
68957 
68958 		duk__advance(comp_ctx);
68959 		return;
68960 	}
68961 	case DUK_TOK_LBRACKET: {
68962 		/* Property access expressions are critical for correct LHS ordering,
68963 		 * see comments in duk__expr()!
68964 		 */
68965 
68966 		/* XXX: optimize temp reg use */
68967 		/* XXX: similar coercion issue as in DUK_TOK_PERIOD */
68968 		/* XXX: coerce to regs? it might be better for enumeration use, where the
68969 		 * same PROP ivalue is used multiple times.  Or perhaps coerce PROP further
68970 		 * there?
68971 		 */
68972 		/* XXX: for simple cases like x['y'] an unnecessary LDREG is
68973 		 * emitted for the base value; could avoid it if we knew that
68974 		 * the key expression is safe (e.g. just a single literal).
68975 		 */
68976 
68977 		/* The 'left' value must not be a register bound variable
68978 		 * because it may be mutated during the rest of the expression
68979 		 * and E5.1 Section 11.2.1 specifies the order of evaluation
68980 		 * so that the base value is evaluated first.
68981 		 * See: test-bug-nested-prop-mutate.js.
68982 		 */
68983 		duk__ivalue_totempconst(comp_ctx, left);
68984 		duk__expr_toplain(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression, ']' terminates */
68985 		duk__advance_expect(comp_ctx, DUK_TOK_RBRACKET);
68986 
68987 		res->t = DUK_IVAL_PROP;
68988 		duk__copy_ispec(comp_ctx, &res->x1, &res->x2);   /* res.x1 -> res.x2 */
68989 		duk__copy_ispec(comp_ctx, &left->x1, &res->x1);  /* left.x1 -> res.x1 */
68990 		return;
68991 	}
68992 	case DUK_TOK_LPAREN: {
68993 		/* function call */
68994 		duk_regconst_t reg_cs = DUK__ALLOCTEMPS(comp_ctx, 2);
68995 		duk_int_t nargs;
68996 		duk_small_uint_t call_op = DUK_OP_CALL0;
68997 
68998 		/* XXX: attempt to get the call result to "next temp" whenever
68999 		 * possible to avoid unnecessary register shuffles.
69000 		 */
69001 
69002 		/*
69003 		 *  Setup call: target and 'this' binding.  Three cases:
69004 		 *
69005 		 *    1. Identifier base (e.g. "foo()")
69006 		 *    2. Property base (e.g. "foo.bar()")
69007 		 *    3. Register base (e.g. "foo()()"; i.e. when a return value is a function)
69008 		 */
69009 
69010 		if (left->t == DUK_IVAL_VAR) {
69011 			duk_hstring *h_varname;
69012 			duk_regconst_t reg_varbind;
69013 			duk_regconst_t rc_varname;
69014 
69015 			DUK_DDD(DUK_DDDPRINT("function call with identifier base"));
69016 
69017 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69018 			if (h_varname == DUK_HTHREAD_STRING_EVAL(thr)) {
69019 				/* Potential direct eval call detected, flag the CALL
69020 				 * so that a run-time "direct eval" check is made and
69021 				 * special behavior may be triggered.  Note that this
69022 				 * does not prevent 'eval' from being register bound.
69023 				 */
69024 				DUK_DDD(DUK_DDDPRINT("function call with identifier 'eval' "
69025 				                     "-> using EVALCALL, marking function "
69026 				                     "as may_direct_eval"));
69027 				call_op |= DUK_BC_CALL_FLAG_CALLED_AS_EVAL;
69028 				comp_ctx->curr_func.may_direct_eval = 1;
69029 			}
69030 
69031 			duk_dup(thr, left->x1.valstack_idx);
69032 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69033 				duk__emit_a_bc(comp_ctx,
69034 				              DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69035 				              reg_varbind,
69036 				              reg_cs + 0);
69037 			} else {
69038 				/* XXX: expand target register or constant field to
69039 				 * reduce shuffling.
69040 				 */
69041 				DUK_ASSERT(DUK__ISCONST(rc_varname));
69042 				duk__emit_a_b(comp_ctx,
69043 				              DUK_OP_CSVAR | DUK__EMIT_FLAG_BC_REGCONST,
69044 				              reg_cs + 0,
69045 				              rc_varname);
69046 			}
69047 		} else if (left->t == DUK_IVAL_PROP) {
69048 			/* Call through a property lookup, E5 Section 11.2.3, step 6.a.i,
69049 			 * E5 Section 10.4.3.  There used to be a separate CSPROP opcode
69050 			 * but a typical call setup took 3 opcodes (e.g. LDREG, LDCONST,
69051 			 * CSPROP) and the same can be achieved with ordinary loads.
69052 			 */
69053 #if defined(DUK_USE_VERBOSE_ERRORS)
69054 			duk_regconst_t reg_key;
69055 #endif
69056 
69057 			DUK_DDD(DUK_DDDPRINT("function call with property base"));
69058 
69059 			/* XXX: For Math.sin() this generates: LDCONST + LDREG +
69060 			 * GETPROPC + call.  The LDREG is unnecessary because LDCONST
69061 			 * could be loaded directly into reg_cs + 1.  This doesn't
69062 			 * happen now because a variable cannot be in left->x1 of a
69063 			 * DUK_IVAL_PROP.  We could notice that left->x1 is a temp
69064 			 * and reuse, but it would still be in the wrong position
69065 			 * (reg_cs + 0 rather than reg_cs + 1).
69066 			 */
69067 			duk__ispec_toforcedreg(comp_ctx, &left->x1, reg_cs + 1);  /* base */
69068 #if defined(DUK_USE_VERBOSE_ERRORS)
69069 			reg_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69070 			duk__emit_a_b_c(comp_ctx,
69071 			                DUK_OP_GETPROPC | DUK__EMIT_FLAG_BC_REGCONST,
69072 			                reg_cs + 0,
69073 			                reg_cs + 1,
69074 			                reg_key);
69075 #else
69076 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);  /* base[key] */
69077 #endif
69078 		} else {
69079 			DUK_DDD(DUK_DDDPRINT("function call with register base"));
69080 
69081 			duk__ivalue_toforcedreg(comp_ctx, left, reg_cs + 0);
69082 #if 0
69083 			duk__emit_a_bc(comp_ctx,
69084 			               DUK_OP_CSREG | DUK__EMIT_FLAG_A_IS_SOURCE,
69085 			               reg_cs + 0,
69086 			               reg_cs + 0);  /* in-place setup */
69087 #endif
69088 			/* Because of in-place setup, REGCS is equivalent to
69089 			 * just this LDUNDEF.
69090 			 */
69091 			duk__emit_bc(comp_ctx, DUK_OP_LDUNDEF, reg_cs + 1);
69092 		}
69093 
69094 		DUK__SETTEMP(comp_ctx, reg_cs + 2);
69095 		nargs = duk__parse_arguments(comp_ctx, res);  /* parse args starting from "next temp" */
69096 
69097 		/* Tailcalls are handled by back-patching the already emitted opcode
69098 		 * later in return statement parser.
69099 		 */
69100 
69101 		duk__emit_a_bc(comp_ctx,
69102 		               call_op,
69103 		               (duk_regconst_t) nargs /*numargs*/,
69104 		               reg_cs /*basereg*/);
69105 		DUK__SETTEMP(comp_ctx, reg_cs + 1);    /* result in csreg */
69106 
69107 		duk__ivalue_regconst(res, reg_cs);
69108 		return;
69109 	}
69110 
69111 	/* POSTFIX EXPRESSION */
69112 
69113 	case DUK_TOK_INCREMENT: {
69114 		args = (DUK_OP_POSTINCP_RR << 16) + (DUK_OP_POSTINCR << 8) + 0;
69115 		goto postincdec;
69116 	}
69117 	case DUK_TOK_DECREMENT: {
69118 		args = (DUK_OP_POSTDECP_RR << 16) + (DUK_OP_POSTDECR << 8) + 0;
69119 		goto postincdec;
69120 	}
69121 
69122 	/* EXPONENTIATION EXPRESSION */
69123 
69124 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69125 	case DUK_TOK_EXP: {
69126 		args = (DUK_OP_EXP << 8) + DUK__BP_EXPONENTIATION - 1;  /* UnaryExpression */
69127 		goto binary;
69128 	}
69129 #endif
69130 
69131 	/* MULTIPLICATIVE EXPRESSION */
69132 
69133 	case DUK_TOK_MUL: {
69134 		args = (DUK_OP_MUL << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69135 		goto binary;
69136 	}
69137 	case DUK_TOK_DIV: {
69138 		args = (DUK_OP_DIV << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69139 		goto binary;
69140 	}
69141 	case DUK_TOK_MOD: {
69142 		args = (DUK_OP_MOD << 8) + DUK__BP_MULTIPLICATIVE;  /* ExponentiationExpression */
69143 		goto binary;
69144 	}
69145 
69146 	/* ADDITIVE EXPRESSION */
69147 
69148 	case DUK_TOK_ADD: {
69149 		args = (DUK_OP_ADD << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69150 		goto binary;
69151 	}
69152 	case DUK_TOK_SUB: {
69153 		args = (DUK_OP_SUB << 8) + DUK__BP_ADDITIVE;  /* MultiplicativeExpression */
69154 		goto binary;
69155 	}
69156 
69157 	/* SHIFT EXPRESSION */
69158 
69159 	case DUK_TOK_ALSHIFT: {
69160 		/* << */
69161 		args = (DUK_OP_BASL << 8) + DUK__BP_SHIFT;
69162 		goto binary;
69163 	}
69164 	case DUK_TOK_ARSHIFT: {
69165 		/* >> */
69166 		args = (DUK_OP_BASR << 8) + DUK__BP_SHIFT;
69167 		goto binary;
69168 	}
69169 	case DUK_TOK_RSHIFT: {
69170 		/* >>> */
69171 		args = (DUK_OP_BLSR << 8) + DUK__BP_SHIFT;
69172 		goto binary;
69173 	}
69174 
69175 	/* RELATIONAL EXPRESSION */
69176 
69177 	case DUK_TOK_LT: {
69178 		/* < */
69179 		args = (DUK_OP_LT << 8) + DUK__BP_RELATIONAL;
69180 		goto binary;
69181 	}
69182 	case DUK_TOK_GT: {
69183 		args = (DUK_OP_GT << 8) + DUK__BP_RELATIONAL;
69184 		goto binary;
69185 	}
69186 	case DUK_TOK_LE: {
69187 		args = (DUK_OP_LE << 8) + DUK__BP_RELATIONAL;
69188 		goto binary;
69189 	}
69190 	case DUK_TOK_GE: {
69191 		args = (DUK_OP_GE << 8) + DUK__BP_RELATIONAL;
69192 		goto binary;
69193 	}
69194 	case DUK_TOK_INSTANCEOF: {
69195 		args = (DUK_OP_INSTOF << 8) + DUK__BP_RELATIONAL;
69196 		goto binary;
69197 	}
69198 	case DUK_TOK_IN: {
69199 		args = (DUK_OP_IN << 8) + DUK__BP_RELATIONAL;
69200 		goto binary;
69201 	}
69202 
69203 	/* EQUALITY EXPRESSION */
69204 
69205 	case DUK_TOK_EQ: {
69206 		args = (DUK_OP_EQ << 8) + DUK__BP_EQUALITY;
69207 		goto binary;
69208 	}
69209 	case DUK_TOK_NEQ: {
69210 		args = (DUK_OP_NEQ << 8) + DUK__BP_EQUALITY;
69211 		goto binary;
69212 	}
69213 	case DUK_TOK_SEQ: {
69214 		args = (DUK_OP_SEQ << 8) + DUK__BP_EQUALITY;
69215 		goto binary;
69216 	}
69217 	case DUK_TOK_SNEQ: {
69218 		args = (DUK_OP_SNEQ << 8) + DUK__BP_EQUALITY;
69219 		goto binary;
69220 	}
69221 
69222 	/* BITWISE EXPRESSIONS */
69223 
69224 	case DUK_TOK_BAND: {
69225 		args = (DUK_OP_BAND << 8) + DUK__BP_BAND;
69226 		goto binary;
69227 	}
69228 	case DUK_TOK_BXOR: {
69229 		args = (DUK_OP_BXOR << 8) + DUK__BP_BXOR;
69230 		goto binary;
69231 	}
69232 	case DUK_TOK_BOR: {
69233 		args = (DUK_OP_BOR << 8) + DUK__BP_BOR;
69234 		goto binary;
69235 	}
69236 
69237 	/* LOGICAL EXPRESSIONS */
69238 
69239 	case DUK_TOK_LAND: {
69240 		/* syntactically left-associative but parsed as right-associative */
69241 		args = (1 << 8) + DUK__BP_LAND - 1;
69242 		goto binary_logical;
69243 	}
69244 	case DUK_TOK_LOR: {
69245 		/* syntactically left-associative but parsed as right-associative */
69246 		args = (0 << 8) + DUK__BP_LOR - 1;
69247 		goto binary_logical;
69248 	}
69249 
69250 	/* CONDITIONAL EXPRESSION */
69251 
69252 	case DUK_TOK_QUESTION: {
69253 		/* XXX: common reg allocation need is to reuse a sub-expression's temp reg,
69254 		 * but only if it really is a temp.  Nothing fancy here now.
69255 		 */
69256 		duk_regconst_t reg_temp;
69257 		duk_int_t pc_jump1;
69258 		duk_int_t pc_jump2;
69259 
69260 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69261 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
69262 		duk__emit_if_true_skip(comp_ctx, reg_temp);
69263 		pc_jump1 = duk__emit_jump_empty(comp_ctx);  /* jump to false */
69264 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69265 		duk__advance_expect(comp_ctx, DUK_TOK_COLON);
69266 		pc_jump2 = duk__emit_jump_empty(comp_ctx);  /* jump to end */
69267 		duk__patch_jump_here(comp_ctx, pc_jump1);
69268 		duk__expr_toforcedreg(comp_ctx, res, DUK__BP_COMMA /*rbp_flags*/, reg_temp /*forced_reg*/);  /* AssignmentExpression */
69269 		duk__patch_jump_here(comp_ctx, pc_jump2);
69270 
69271 		DUK__SETTEMP(comp_ctx, reg_temp + 1);
69272 		duk__ivalue_regconst(res, reg_temp);
69273 		return;
69274 	}
69275 
69276 	/* ASSIGNMENT EXPRESSION */
69277 
69278 	case DUK_TOK_EQUALSIGN: {
69279 		/*
69280 		 *  Assignments are right associative, allows e.g.
69281 		 *    a = 5;
69282 		 *    a += b = 9;   // same as a += (b = 9)
69283 		 *  -> expression value 14, a = 14, b = 9
69284 		 *
69285 		 *  Right associativiness is reflected in the BP for recursion,
69286 		 *  "-1" ensures assignment operations are allowed.
69287 		 *
69288 		 *  XXX: just use DUK__BP_COMMA (i.e. no need for 2-step bp levels)?
69289 		 */
69290 		args = (DUK_OP_NONE << 8) + DUK__BP_ASSIGNMENT - 1;   /* DUK_OP_NONE marks a 'plain' assignment */
69291 		goto assign;
69292 	}
69293 	case DUK_TOK_ADD_EQ: {
69294 		/* right associative */
69295 		args = (DUK_OP_ADD << 8) + DUK__BP_ASSIGNMENT - 1;
69296 		goto assign;
69297 	}
69298 	case DUK_TOK_SUB_EQ: {
69299 		/* right associative */
69300 		args = (DUK_OP_SUB << 8) + DUK__BP_ASSIGNMENT - 1;
69301 		goto assign;
69302 	}
69303 	case DUK_TOK_MUL_EQ: {
69304 		/* right associative */
69305 		args = (DUK_OP_MUL << 8) + DUK__BP_ASSIGNMENT - 1;
69306 		goto assign;
69307 	}
69308 	case DUK_TOK_DIV_EQ: {
69309 		/* right associative */
69310 		args = (DUK_OP_DIV << 8) + DUK__BP_ASSIGNMENT - 1;
69311 		goto assign;
69312 	}
69313 	case DUK_TOK_MOD_EQ: {
69314 		/* right associative */
69315 		args = (DUK_OP_MOD << 8) + DUK__BP_ASSIGNMENT - 1;
69316 		goto assign;
69317 	}
69318 #if defined(DUK_USE_ES7_EXP_OPERATOR)
69319 	case DUK_TOK_EXP_EQ: {
69320 		/* right associative */
69321 		args = (DUK_OP_EXP << 8) + DUK__BP_ASSIGNMENT - 1;
69322 		goto assign;
69323 	}
69324 #endif
69325 	case DUK_TOK_ALSHIFT_EQ: {
69326 		/* right associative */
69327 		args = (DUK_OP_BASL << 8) + DUK__BP_ASSIGNMENT - 1;
69328 		goto assign;
69329 	}
69330 	case DUK_TOK_ARSHIFT_EQ: {
69331 		/* right associative */
69332 		args = (DUK_OP_BASR << 8) + DUK__BP_ASSIGNMENT - 1;
69333 		goto assign;
69334 	}
69335 	case DUK_TOK_RSHIFT_EQ: {
69336 		/* right associative */
69337 		args = (DUK_OP_BLSR << 8) + DUK__BP_ASSIGNMENT - 1;
69338 		goto assign;
69339 	}
69340 	case DUK_TOK_BAND_EQ: {
69341 		/* right associative */
69342 		args = (DUK_OP_BAND << 8) + DUK__BP_ASSIGNMENT - 1;
69343 		goto assign;
69344 	}
69345 	case DUK_TOK_BOR_EQ: {
69346 		/* right associative */
69347 		args = (DUK_OP_BOR << 8) + DUK__BP_ASSIGNMENT - 1;
69348 		goto assign;
69349 	}
69350 	case DUK_TOK_BXOR_EQ: {
69351 		/* right associative */
69352 		args = (DUK_OP_BXOR << 8) + DUK__BP_ASSIGNMENT - 1;
69353 		goto assign;
69354 	}
69355 
69356 	/* COMMA */
69357 
69358 	case DUK_TOK_COMMA: {
69359 		/* right associative */
69360 
69361 		duk__ivalue_toplain_ignore(comp_ctx, left);  /* need side effects, not value */
69362 		duk__expr_toplain(comp_ctx, res, DUK__BP_COMMA - 1 /*rbp_flags*/);
69363 
69364 		/* return 'res' (of right part) as our result */
69365 		return;
69366 	}
69367 
69368 	default: {
69369 		break;
69370 	}
69371 	}
69372 
69373 	DUK_D(DUK_DPRINT("parse error: unexpected token: %ld", (long) tok));
69374 	DUK_ERROR_SYNTAX(thr, DUK_STR_PARSE_ERROR);
69375 	DUK_WO_NORETURN(return;);
69376 
69377 #if 0
69378 	/* XXX: shared handling for 'duk__expr_lhs'? */
69379 	if (comp_ctx->curr_func.paren_level == 0 && XXX) {
69380 		comp_ctx->curr_func.duk__expr_lhs = 0;
69381 	}
69382 #endif
69383 
69384  binary:
69385 	/*
69386 	 *  Shared handling of binary operations
69387 	 *
69388 	 *  args = (opcode << 8) + rbp
69389 	 */
69390 	{
69391 		duk__ivalue_toplain(comp_ctx, left);
69392 		duk__expr_toplain(comp_ctx, res, args & 0xff /*rbp_flags*/);
69393 
69394 		/* combine left->x1 and res->x1 (right->x1, really) -> (left->x1 OP res->x1) */
69395 		DUK_ASSERT(left->t == DUK_IVAL_PLAIN);
69396 		DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
69397 
69398 		res->t = DUK_IVAL_ARITH;
69399 		res->op = (args >> 8) & 0xff;
69400 
69401 		res->x2.t = res->x1.t;
69402 		res->x2.regconst = res->x1.regconst;
69403 		duk_copy(thr, res->x1.valstack_idx, res->x2.valstack_idx);
69404 
69405 		res->x1.t = left->x1.t;
69406 		res->x1.regconst = left->x1.regconst;
69407 		duk_copy(thr, left->x1.valstack_idx, res->x1.valstack_idx);
69408 
69409 		DUK_DDD(DUK_DDDPRINT("binary op, res: t=%ld, x1.t=%ld, x1.regconst=0x%08lx, x2.t=%ld, x2.regconst=0x%08lx",
69410 		                     (long) res->t, (long) res->x1.t, (unsigned long) res->x1.regconst, (long) res->x2.t, (unsigned long) res->x2.regconst));
69411 		return;
69412 	}
69413 
69414  binary_logical:
69415 	/*
69416 	 *  Shared handling for logical AND and logical OR.
69417 	 *
69418 	 *  args = (truthval << 8) + rbp
69419 	 *
69420 	 *  Truthval determines when to skip right-hand-side.
69421 	 *  For logical AND truthval=1, for logical OR truthval=0.
69422 	 *
69423 	 *  See doc/compiler.rst for discussion on compiling logical
69424 	 *  AND and OR expressions.  The approach here is very simplistic,
69425 	 *  generating extra jumps and multiple evaluations of truth values,
69426 	 *  but generates code on-the-fly with only local back-patching.
69427 	 *
69428 	 *  Both logical AND and OR are syntactically left-associated.
69429 	 *  However, logical ANDs are compiled as right associative
69430 	 *  expressions, i.e. "A && B && C" as "A && (B && C)", to allow
69431 	 *  skip jumps to skip over the entire tail.  Similarly for logical OR.
69432 	 */
69433 
69434 	{
69435 		duk_regconst_t reg_temp;
69436 		duk_int_t pc_jump;
69437 		duk_small_uint_t args_truthval = args >> 8;
69438 		duk_small_uint_t args_rbp = args & 0xff;
69439 
69440 		/* XXX: unoptimal use of temps, resetting */
69441 
69442 		reg_temp = DUK__ALLOCTEMP(comp_ctx);
69443 
69444 		duk__ivalue_toforcedreg(comp_ctx, left, reg_temp);
69445 		DUK_ASSERT(DUK__ISREG(reg_temp));
69446 		duk__emit_bc(comp_ctx,
69447 		            (args_truthval ? DUK_OP_IFTRUE_R : DUK_OP_IFFALSE_R),
69448 		            reg_temp);  /* skip jump conditionally */
69449 		pc_jump = duk__emit_jump_empty(comp_ctx);
69450 		duk__expr_toforcedreg(comp_ctx, res, args_rbp /*rbp_flags*/, reg_temp /*forced_reg*/);
69451 		duk__patch_jump_here(comp_ctx, pc_jump);
69452 
69453 		duk__ivalue_regconst(res, reg_temp);
69454 		return;
69455 	}
69456 
69457  assign:
69458 	/*
69459 	 *  Shared assignment expression handling
69460 	 *
69461 	 *  args = (opcode << 8) + rbp
69462 	 *
69463 	 *  If 'opcode' is DUK_OP_NONE, plain assignment without arithmetic.
69464 	 *  Syntactically valid left-hand-side forms which are not accepted as
69465 	 *  left-hand-side values (e.g. as in "f() = 1") must NOT cause a
69466 	 *  SyntaxError, but rather a run-time ReferenceError.
69467 	 *
69468 	 *  When evaluating X <op>= Y, the LHS (X) is conceptually evaluated
69469 	 *  to a temporary first.  The RHS is then evaluated.  Finally, the
69470 	 *  <op> is applied to the initial value of RHS (not the value after
69471 	 *  RHS evaluation), and written to X.  Doing so concretely generates
69472 	 *  inefficient code so we'd like to avoid the temporary when possible.
69473 	 *  See: https://github.com/svaarala/duktape/pull/992.
69474 	 *
69475 	 *  The expression value (final LHS value, written to RHS) is
69476 	 *  conceptually copied into a fresh temporary so that it won't
69477 	 *  change even if the LHS/RHS values change in outer expressions.
69478 	 *  For example, it'd be generally incorrect for the expression value
69479 	 *  to be the RHS register binding, unless there's a guarantee that it
69480 	 *  won't change during further expression evaluation.  Using the
69481 	 *  temporary concretely produces inefficient bytecode, so we try to
69482 	 *  avoid the extra temporary for some known-to-be-safe cases.
69483 	 *  Currently the only safe case we detect is a "top level assignment",
69484 	 *  for example "x = y + z;", where the assignment expression value is
69485 	 *  ignored.
69486 	 *  See: test-dev-assign-expr.js and test-bug-assign-mutate-gh381.js.
69487 	 */
69488 
69489 	{
69490 		duk_small_uint_t args_op = args >> 8;
69491 		duk_small_uint_t args_rbp = args & 0xff;
69492 		duk_bool_t toplevel_assign;
69493 
69494 		/* XXX: here we need to know if 'left' is left-hand-side compatible.
69495 		 * That information is no longer available from current expr parsing
69496 		 * state; it would need to be carried into the 'left' ivalue or by
69497 		 * some other means.
69498 		 */
69499 
69500 		/* A top-level assignment is e.g. "x = y;".  For these it's safe
69501 		 * to use the RHS as-is as the expression value, even if the RHS
69502 		 * is a reg-bound identifier.  The RHS ('res') is right associative
69503 		 * so it has consumed all other assignment level operations; the
69504 		 * only relevant lower binding power construct is comma operator
69505 		 * which will ignore the expression value provided here.  Usually
69506 		 * the top level assignment expression value is ignored, but it
69507 		 * is relevant for e.g. eval code.
69508 		 */
69509 		toplevel_assign = (comp_ctx->curr_func.nud_count == 1 && /* one token before */
69510 		                   comp_ctx->curr_func.led_count == 1);  /* one operator (= assign) */
69511 		DUK_DDD(DUK_DDDPRINT("assignment: nud_count=%ld, led_count=%ld, toplevel_assign=%ld",
69512 		                     (long) comp_ctx->curr_func.nud_count,
69513 		                     (long) comp_ctx->curr_func.led_count,
69514 		                     (long) toplevel_assign));
69515 
69516 		if (left->t == DUK_IVAL_VAR) {
69517 			duk_hstring *h_varname;
69518 			duk_regconst_t reg_varbind;
69519 			duk_regconst_t rc_varname;
69520 
69521 			DUK_ASSERT(left->x1.t == DUK_ISPEC_VALUE);  /* LHS is already side effect free */
69522 
69523 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69524 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
69525 				/* E5 Section 11.13.1 (and others for other assignments), step 4. */
69526 				goto syntax_error_lvalue;
69527 			}
69528 			duk_dup(thr, left->x1.valstack_idx);
69529 			(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
69530 
69531 			if (args_op == DUK_OP_NONE) {
69532 				duk__expr(comp_ctx, res, args_rbp /*rbp_flags*/);
69533 				if (toplevel_assign) {
69534 					/* Any 'res' will do. */
69535 					DUK_DDD(DUK_DDDPRINT("plain assignment, toplevel assign, use as is"));
69536 				} else {
69537 					/* 'res' must be a plain ivalue, and not register-bound variable. */
69538 					DUK_DDD(DUK_DDDPRINT("plain assignment, not toplevel assign, ensure not a reg-bound identifier"));
69539 					if (res->t != DUK_IVAL_PLAIN || (res->x1.t == DUK_ISPEC_REGCONST &&
69540 					                                 DUK__ISREG_NOTTEMP(comp_ctx, res->x1.regconst))) {
69541 						duk__ivalue_totempconst(comp_ctx, res);
69542 					}
69543 				}
69544 			} else {
69545 				/* For X <op>= Y we need to evaluate the pre-op
69546 				 * value of X before evaluating the RHS: the RHS
69547 				 * can change X, but when we do <op> we must use
69548 				 * the pre-op value.
69549 				 */
69550 				duk_regconst_t reg_temp;
69551 
69552 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
69553 
69554 				if (reg_varbind >= 0) {
69555 					duk_regconst_t reg_res;
69556 					duk_regconst_t reg_src;
69557 					duk_int_t pc_temp_load;
69558 					duk_int_t pc_before_rhs;
69559 					duk_int_t pc_after_rhs;
69560 
69561 					if (toplevel_assign) {
69562 						/* 'reg_varbind' is the operation result and can also
69563 						 * become the expression value for top level assignments
69564 						 * such as: "var x; x += y;".
69565 						 */
69566 						DUK_DD(DUK_DDPRINT("<op>= expression is top level, write directly to reg_varbind"));
69567 						reg_res = reg_varbind;
69568 					} else {
69569 						/* Not safe to use 'reg_varbind' as assignment expression
69570 						 * value, so go through a temp.
69571 						 */
69572 						DUK_DD(DUK_DDPRINT("<op>= expression is not top level, write to reg_temp"));
69573 						reg_res = reg_temp;  /* reg_res should be smallest possible */
69574 						reg_temp = DUK__ALLOCTEMP(comp_ctx);
69575 					}
69576 
69577 					/* Try to optimize X <op>= Y for reg-bound
69578 					 * variables.  Detect side-effect free RHS
69579 					 * narrowly by seeing whether it emits code.
69580 					 * If not, rewind the code emitter and overwrite
69581 					 * the unnecessary temp reg load.
69582 					 */
69583 
69584 					pc_temp_load = duk__get_current_pc(comp_ctx);
69585 					duk__emit_a_bc(comp_ctx,
69586 					               DUK_OP_LDREG,
69587 					               reg_temp,
69588 					               reg_varbind);
69589 
69590 					pc_before_rhs = duk__get_current_pc(comp_ctx);
69591 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69592 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69593 					pc_after_rhs = duk__get_current_pc(comp_ctx);
69594 
69595 					DUK_DD(DUK_DDPRINT("pc_temp_load=%ld, pc_before_rhs=%ld, pc_after_rhs=%ld",
69596 					                   (long) pc_temp_load, (long) pc_before_rhs,
69597 					                   (long) pc_after_rhs));
69598 
69599 					if (pc_after_rhs == pc_before_rhs) {
69600 						/* Note: if the reg_temp load generated shuffling
69601 						 * instructions, we may need to rewind more than
69602 						 * one instruction, so use explicit PC computation.
69603 						 */
69604 						DUK_DD(DUK_DDPRINT("rhs is side effect free, rewind and avoid unnecessary temp for reg-based <op>="));
69605 						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));
69606 						reg_src = reg_varbind;
69607 					} else {
69608 						DUK_DD(DUK_DDPRINT("rhs evaluation emitted code, not sure if rhs is side effect free; use temp reg for LHS"));
69609 						reg_src = reg_temp;
69610 					}
69611 
69612 					duk__emit_a_b_c(comp_ctx,
69613 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69614 					                reg_res,
69615 					                reg_src,
69616 					                res->x1.regconst);
69617 
69618 					res->x1.regconst = reg_res;
69619 
69620 					/* Ensure compact use of temps. */
69621 					if (DUK__ISREG_TEMP(comp_ctx, reg_res)) {
69622 						DUK__SETTEMP(comp_ctx, reg_res + 1);
69623 					}
69624 				} else {
69625 					/* When LHS is not register bound, always go through a
69626 					 * temporary.  No optimization for top level assignment.
69627 					 */
69628 
69629 					duk__emit_a_bc(comp_ctx,
69630 					               DUK_OP_GETVAR,
69631 					               reg_temp,
69632 					               rc_varname);
69633 
69634 					duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69635 					DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69636 
69637 					duk__emit_a_b_c(comp_ctx,
69638 					                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69639 					                reg_temp,
69640 					                reg_temp,
69641 					                res->x1.regconst);
69642 					res->x1.regconst = reg_temp;
69643 				}
69644 
69645 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69646 			}
69647 
69648 			/* At this point 'res' holds the potential expression value.
69649 			 * It can be basically any ivalue here, including a reg-bound
69650 			 * identifier (if code above deems it safe) or a unary/binary
69651 			 * operation.  Operations must be resolved to a side effect free
69652 			 * plain value, and the side effects must happen exactly once.
69653 			 */
69654 
69655 			if (reg_varbind >= 0) {
69656 				if (res->t != DUK_IVAL_PLAIN) {
69657 					/* Resolve 'res' directly into the LHS binding, and use
69658 					 * that as the expression value if safe.  If not safe,
69659 					 * resolve to a temp/const and copy to LHS.
69660 					 */
69661 					if (toplevel_assign) {
69662 						duk__ivalue_toforcedreg(comp_ctx, res, (duk_int_t) reg_varbind);
69663 					} else {
69664 						duk__ivalue_totempconst(comp_ctx, res);
69665 						duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
69666 						duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
69667 					}
69668 				} else {
69669 					/* Use 'res' as the expression value (it's side effect
69670 					 * free and may be a plain value, a register, or a
69671 					 * constant) and write it to the LHS binding too.
69672 					 */
69673 					duk__copy_ivalue(comp_ctx, res, left);  /* use 'left' as a temp */
69674 					duk__ivalue_toforcedreg(comp_ctx, left, (duk_int_t) reg_varbind);
69675 				}
69676 			} else {
69677 				/* Only a reg fits into 'A' so coerce 'res' into a register
69678 				 * for PUTVAR.
69679 				 *
69680 				 * XXX: here the current A/B/C split is suboptimal: we could
69681 				 * just use 9 bits for reg_res (and support constants) and 17
69682 				 * instead of 18 bits for the varname const index.
69683 				 */
69684 
69685 				duk__ivalue_toreg(comp_ctx, res);
69686 				duk__emit_a_bc(comp_ctx,
69687 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
69688 				               res->x1.regconst,
69689 				               rc_varname);
69690 			}
69691 
69692 			/* 'res' contains expression value */
69693 		} else if (left->t == DUK_IVAL_PROP) {
69694 			/* E5 Section 11.13.1 (and others) step 4 never matches for prop writes -> no check */
69695 			duk_regconst_t reg_obj;
69696 			duk_regconst_t rc_key;
69697 			duk_regconst_t rc_res;
69698 			duk_regconst_t reg_temp;
69699 
69700 			/* Property access expressions ('a[b]') are critical to correct
69701 			 * LHS evaluation ordering, see test-dev-assign-eval-order*.js.
69702 			 * We must make sure that the LHS target slot (base object and
69703 			 * key) don't change during RHS evaluation.  The only concrete
69704 			 * problem is a register reference to a variable-bound register
69705 			 * (i.e., non-temp).  Require temp regs for both key and base.
69706 			 *
69707 			 * Don't allow a constant for the object (even for a number
69708 			 * etc), as it goes into the 'A' field of the opcode.
69709 			 */
69710 
69711 			reg_obj = duk__ispec_toregconst_raw(comp_ctx,
69712 			                                    &left->x1,
69713 			                                    -1 /*forced_reg*/,
69714 			                                    DUK__IVAL_FLAG_REQUIRE_TEMP /*flags*/);
69715 
69716 			rc_key = duk__ispec_toregconst_raw(comp_ctx,
69717 			                                   &left->x2,
69718 			                                   -1 /*forced_reg*/,
69719 			                                   DUK__IVAL_FLAG_REQUIRE_TEMP | DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69720 
69721 			/* Evaluate RHS only when LHS is safe. */
69722 
69723 			if (args_op == DUK_OP_NONE) {
69724 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69725 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69726 				rc_res = res->x1.regconst;
69727 			} else {
69728 				reg_temp = DUK__ALLOCTEMP(comp_ctx);
69729 				duk__emit_a_b_c(comp_ctx,
69730 				                DUK_OP_GETPROP | DUK__EMIT_FLAG_BC_REGCONST,
69731 				                reg_temp,
69732 				                reg_obj,
69733 				                rc_key);
69734 
69735 				duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69736 				DUK_ASSERT(res->t == DUK_IVAL_PLAIN && res->x1.t == DUK_ISPEC_REGCONST);
69737 
69738 				duk__emit_a_b_c(comp_ctx,
69739 				                args_op | DUK__EMIT_FLAG_BC_REGCONST,
69740 				                reg_temp,
69741 				                reg_temp,
69742 				                res->x1.regconst);
69743 				rc_res = reg_temp;
69744 			}
69745 
69746 			duk__emit_a_b_c(comp_ctx,
69747 			                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
69748 			                reg_obj,
69749 			                rc_key,
69750 			                rc_res);
69751 
69752 			duk__ivalue_regconst(res, rc_res);
69753 		} else {
69754 			/* No support for lvalues returned from new or function call expressions.
69755 			 * However, these must NOT cause compile-time SyntaxErrors, but run-time
69756 			 * ReferenceErrors.  Both left and right sides of the assignment must be
69757 			 * evaluated before throwing a ReferenceError.  For instance:
69758 			 *
69759 			 *     f() = g();
69760 			 *
69761 			 * must result in f() being evaluated, then g() being evaluated, and
69762 			 * finally, a ReferenceError being thrown.  See E5 Section 11.13.1.
69763 			 */
69764 
69765 			duk_regconst_t rc_res;
69766 
69767 			/* First evaluate LHS fully to ensure all side effects are out. */
69768 			duk__ivalue_toplain_ignore(comp_ctx, left);
69769 
69770 			/* Then evaluate RHS fully (its value becomes the expression value too).
69771 			 * Technically we'd need the side effect safety check here too, but because
69772 			 * we always throw using INVLHS the result doesn't matter.
69773 			 */
69774 			rc_res = duk__expr_toregconst(comp_ctx, res, args_rbp /*rbp_flags*/);
69775 
69776 			duk__emit_op_only(comp_ctx, DUK_OP_INVLHS);
69777 
69778 			duk__ivalue_regconst(res, rc_res);
69779 		}
69780 
69781 		return;
69782 	}
69783 
69784  postincdec:
69785 	{
69786 		/*
69787 		 *  Post-increment/decrement will return the original value as its
69788 		 *  result value.  However, even that value will be coerced using
69789 		 *  ToNumber() which is quite awkward.  Specific bytecode opcodes
69790 		 *  are used to handle these semantics.
69791 		 *
69792 		 *  Note that post increment/decrement has a "no LineTerminator here"
69793 		 *  restriction.  This is handled by duk__expr_lbp(), which forcibly terminates
69794 		 *  the previous expression if a LineTerminator occurs before '++'/'--'.
69795 		 */
69796 
69797 		duk_regconst_t reg_res;
69798 		duk_small_uint_t args_op1 = (args >> 8) & 0xff;  /* DUK_OP_POSTINCR/DUK_OP_POSTDECR */
69799 		duk_small_uint_t args_op2 = args >> 16;          /* DUK_OP_POSTINCP_RR/DUK_OP_POSTDECP_RR */
69800 
69801 		/* Specific assumptions for opcode numbering. */
69802 		DUK_ASSERT(DUK_OP_POSTINCR + 4 == DUK_OP_POSTINCV);
69803 		DUK_ASSERT(DUK_OP_POSTDECR + 4 == DUK_OP_POSTDECV);
69804 
69805 		reg_res = DUK__ALLOCTEMP(comp_ctx);
69806 
69807 		if (left->t == DUK_IVAL_VAR) {
69808 			duk_hstring *h_varname;
69809 			duk_regconst_t reg_varbind;
69810 			duk_regconst_t rc_varname;
69811 
69812 			h_varname = duk_known_hstring(thr, left->x1.valstack_idx);
69813 
69814 			if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
69815 				goto syntax_error;
69816 			}
69817 
69818 			duk_dup(thr, left->x1.valstack_idx);
69819 			if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
69820 				duk__emit_a_bc(comp_ctx,
69821 				               args_op1,  /* e.g. DUK_OP_POSTINCR */
69822 				               reg_res,
69823 				               reg_varbind);
69824 			} else {
69825 				duk__emit_a_bc(comp_ctx,
69826 				               args_op1 + 4,  /* e.g. DUK_OP_POSTINCV */
69827 				               reg_res,
69828 				               rc_varname);
69829 			}
69830 
69831 			DUK_DDD(DUK_DDDPRINT("postincdec to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
69832 			                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
69833 		} else if (left->t == DUK_IVAL_PROP) {
69834 			duk_regconst_t reg_obj;  /* allocate to reg only (not const) */
69835 			duk_regconst_t rc_key;
69836 
69837 			reg_obj = duk__ispec_toregconst_raw(comp_ctx, &left->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
69838 			rc_key = duk__ispec_toregconst_raw(comp_ctx, &left->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
69839 			duk__emit_a_b_c(comp_ctx,
69840 			                args_op2 | DUK__EMIT_FLAG_BC_REGCONST,  /* e.g. DUK_OP_POSTINCP */
69841 			                reg_res,
69842 			                reg_obj,
69843 			                rc_key);
69844 		} else {
69845 			/* Technically return value is not needed because INVLHS will
69846 			 * unconditially throw a ReferenceError.  Coercion is necessary
69847 			 * for proper semantics (consider ToNumber() called for an object).
69848 			 * Use DUK_OP_UNP with a dummy register to get ToNumber().
69849 			 */
69850 			duk__ivalue_toforcedreg(comp_ctx, left, reg_res);
69851 			duk__emit_bc(comp_ctx,
69852 			             DUK_OP_UNP,
69853 			             reg_res);  /* for side effects, result ignored */
69854 			duk__emit_op_only(comp_ctx,
69855 			                  DUK_OP_INVLHS);
69856 		}
69857 
69858 		DUK__SETTEMP(comp_ctx, reg_res + 1);
69859 		duk__ivalue_regconst(res, reg_res);
69860 		return;
69861 	}
69862 
69863  syntax_error:
69864 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_EXPRESSION);
69865 	DUK_WO_NORETURN(return;);
69866 
69867  syntax_error_lvalue:
69868 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_LVALUE);
69869 	DUK_WO_NORETURN(return;);
69870 }
69871 
69872 DUK_LOCAL duk_small_uint_t duk__expr_lbp(duk_compiler_ctx *comp_ctx) {
69873 	duk_small_uint_t tok = comp_ctx->curr_token.t;
69874 
69875 	DUK_ASSERT_DISABLE(tok >= DUK_TOK_MINVAL);  /* unsigned */
69876 	DUK_ASSERT(tok <= DUK_TOK_MAXVAL);
69877 	DUK_ASSERT(sizeof(duk__token_lbp) == DUK_TOK_MAXVAL + 1);
69878 
69879 	/* XXX: integrate support for this into led() instead?
69880 	 * Similar issue as post-increment/post-decrement.
69881 	 */
69882 
69883 	/* prevent duk__expr_led() by using a binding power less than anything valid */
69884 	if (tok == DUK_TOK_IN && !comp_ctx->curr_func.allow_in) {
69885 		return 0;
69886 	}
69887 
69888 	if ((tok == DUK_TOK_DECREMENT || tok == DUK_TOK_INCREMENT) &&
69889 	    (comp_ctx->curr_token.lineterm)) {
69890 		/* '++' or '--' in a post-increment/decrement position,
69891 		 * and a LineTerminator occurs between the operator and
69892 		 * the preceding expression.  Force the previous expr
69893 		 * to terminate, in effect treating e.g. "a,b\n++" as
69894 		 * "a,b;++" (= SyntaxError).
69895 		 */
69896 		return 0;
69897 	}
69898 
69899 	return DUK__TOKEN_LBP_GET_BP(duk__token_lbp[tok]);  /* format is bit packed */
69900 }
69901 
69902 /*
69903  *  Expression parsing.
69904  *
69905  *  Upon entry to 'expr' and its variants, 'curr_tok' is assumed to be the
69906  *  first token of the expression.  Upon exit, 'curr_tok' will be the first
69907  *  token not part of the expression (e.g. semicolon terminating an expression
69908  *  statement).
69909  */
69910 
69911 #define DUK__EXPR_RBP_MASK           0xff
69912 #define DUK__EXPR_FLAG_REJECT_IN     (1 << 8)   /* reject 'in' token (used for for-in) */
69913 #define DUK__EXPR_FLAG_ALLOW_EMPTY   (1 << 9)   /* allow empty expression */
69914 #define DUK__EXPR_FLAG_REQUIRE_INIT  (1 << 10)  /* require initializer for var/const */
69915 
69916 /* main expression parser function */
69917 DUK_LOCAL void duk__expr(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
69918 	duk_hthread *thr = comp_ctx->thr;
69919 	duk_ivalue tmp_alloc;   /* 'res' is used for "left", and 'tmp' for "right" */
69920 	duk_ivalue *tmp = &tmp_alloc;
69921 	duk_small_uint_t rbp;
69922 
69923 	DUK__RECURSION_INCREASE(comp_ctx, thr);
69924 
69925 	duk_require_stack(thr, DUK__PARSE_EXPR_SLOTS);
69926 
69927 	/* filter out flags from exprtop rbp_flags here to save space */
69928 	rbp = rbp_flags & DUK__EXPR_RBP_MASK;
69929 
69930 	DUK_DDD(DUK_DDDPRINT("duk__expr(), rbp_flags=%ld, rbp=%ld, allow_in=%ld, paren_level=%ld",
69931 	                     (long) rbp_flags, (long) rbp, (long) comp_ctx->curr_func.allow_in,
69932 	                     (long) comp_ctx->curr_func.paren_level));
69933 
69934 	duk_memzero(&tmp_alloc, sizeof(tmp_alloc));
69935 	tmp->x1.valstack_idx = duk_get_top(thr);
69936 	tmp->x2.valstack_idx = tmp->x1.valstack_idx + 1;
69937 	duk_push_undefined(thr);
69938 	duk_push_undefined(thr);
69939 
69940 	/* XXX: where to release temp regs in intermediate expressions?
69941 	 * e.g. 1+2+3 -> don't inflate temp register count when parsing this.
69942 	 * that particular expression temp regs can be forced here.
69943 	 */
69944 
69945 	/* XXX: increase ctx->expr_tokens here for every consumed token
69946 	 * (this would be a nice statistic)?
69947 	 */
69948 
69949 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON || comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
69950 		/* XXX: possibly incorrect handling of empty expression */
69951 		DUK_DDD(DUK_DDDPRINT("empty expression"));
69952 		if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY)) {
69953 			DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
69954 			DUK_WO_NORETURN(return;);
69955 		}
69956 		duk_push_undefined(thr);
69957 		duk__ivalue_plain_fromstack(comp_ctx, res);
69958 		goto cleanup;
69959 	}
69960 
69961 	duk__advance(comp_ctx);
69962 	duk__expr_nud(comp_ctx, res);  /* reuse 'res' as 'left' */
69963 	while (rbp < duk__expr_lbp(comp_ctx)) {
69964 		duk__advance(comp_ctx);
69965 		duk__expr_led(comp_ctx, res, tmp);
69966 		duk__copy_ivalue(comp_ctx, tmp, res);  /* tmp -> res */
69967 	}
69968 
69969  cleanup:
69970 	/* final result is already in 'res' */
69971 
69972 	duk_pop_2(thr);
69973 
69974 	DUK__RECURSION_DECREASE(comp_ctx, thr);
69975 }
69976 
69977 DUK_LOCAL void duk__exprtop(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
69978 	duk_hthread *thr = comp_ctx->thr;
69979 
69980 	/* Note: these variables must reside in 'curr_func' instead of the global
69981 	 * context: when parsing function expressions, expression parsing is nested.
69982 	 */
69983 	comp_ctx->curr_func.nud_count = 0;
69984 	comp_ctx->curr_func.led_count = 0;
69985 	comp_ctx->curr_func.paren_level = 0;
69986 	comp_ctx->curr_func.expr_lhs = 1;
69987 	comp_ctx->curr_func.allow_in = (rbp_flags & DUK__EXPR_FLAG_REJECT_IN ? 0 : 1);
69988 
69989 	duk__expr(comp_ctx, res, rbp_flags);
69990 
69991 	if (!(rbp_flags & DUK__EXPR_FLAG_ALLOW_EMPTY) && duk__expr_is_empty(comp_ctx)) {
69992 		DUK_ERROR_SYNTAX(thr, DUK_STR_EMPTY_EXPR_NOT_ALLOWED);
69993 		DUK_WO_NORETURN(return;);
69994 	}
69995 }
69996 
69997 /* A bunch of helpers (for size optimization) that combine duk__expr()/duk__exprtop()
69998  * and result conversions.
69999  *
70000  * Each helper needs at least 2-3 calls to make it worth while to wrap.
70001  */
70002 
70003 #if 0  /* unused */
70004 DUK_LOCAL duk_regconst_t duk__expr_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70005 	duk__expr(comp_ctx, res, rbp_flags);
70006 	return duk__ivalue_toreg(comp_ctx, res);
70007 }
70008 #endif
70009 
70010 #if 0  /* unused */
70011 DUK_LOCAL duk_regconst_t duk__expr_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70012 	duk__expr(comp_ctx, res, rbp_flags);
70013 	return duk__ivalue_totemp(comp_ctx, res);
70014 }
70015 #endif
70016 
70017 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) {
70018 	DUK_ASSERT(forced_reg >= 0);
70019 	duk__expr(comp_ctx, res, rbp_flags);
70020 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70021 }
70022 
70023 DUK_LOCAL duk_regconst_t duk__expr_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70024 	duk__expr(comp_ctx, res, rbp_flags);
70025 	return duk__ivalue_toregconst(comp_ctx, res);
70026 }
70027 
70028 #if 0  /* unused */
70029 DUK_LOCAL duk_regconst_t duk__expr_totempconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70030 	duk__expr(comp_ctx, res, rbp_flags);
70031 	return duk__ivalue_totempconst(comp_ctx, res);
70032 }
70033 #endif
70034 
70035 DUK_LOCAL void duk__expr_toplain(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70036 	duk__expr(comp_ctx, res, rbp_flags);
70037 	duk__ivalue_toplain(comp_ctx, res);
70038 }
70039 
70040 DUK_LOCAL void duk__expr_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70041 	duk__expr(comp_ctx, res, rbp_flags);
70042 	duk__ivalue_toplain_ignore(comp_ctx, res);
70043 }
70044 
70045 DUK_LOCAL duk_regconst_t duk__exprtop_toreg(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70046 	duk__exprtop(comp_ctx, res, rbp_flags);
70047 	return duk__ivalue_toreg(comp_ctx, res);
70048 }
70049 
70050 #if 0  /* unused */
70051 DUK_LOCAL duk_regconst_t duk__exprtop_totemp(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70052 	duk__exprtop(comp_ctx, res, rbp_flags);
70053 	return duk__ivalue_totemp(comp_ctx, res);
70054 }
70055 #endif
70056 
70057 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) {
70058 	DUK_ASSERT(forced_reg >= 0);
70059 	duk__exprtop(comp_ctx, res, rbp_flags);
70060 	duk__ivalue_toforcedreg(comp_ctx, res, forced_reg);
70061 }
70062 
70063 DUK_LOCAL duk_regconst_t duk__exprtop_toregconst(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t rbp_flags) {
70064 	duk__exprtop(comp_ctx, res, rbp_flags);
70065 	return duk__ivalue_toregconst(comp_ctx, res);
70066 }
70067 
70068 #if 0  /* unused */
70069 DUK_LOCAL void duk__exprtop_toplain_ignore(duk_compiler_ctx *comp_ctx, duk_ivalue *res, int rbp_flags) {
70070 	duk__exprtop(comp_ctx, res, rbp_flags);
70071 	duk__ivalue_toplain_ignore(comp_ctx, res);
70072 }
70073 #endif
70074 
70075 /*
70076  *  Parse an individual source element (top level statement) or a statement.
70077  *
70078  *  Handles labeled statements automatically (peeling away labels before
70079  *  parsing an expression that follows the label(s)).
70080  *
70081  *  Upon entry, 'curr_tok' contains the first token of the statement (parsed
70082  *  in "allow regexp literal" mode).  Upon exit, 'curr_tok' contains the first
70083  *  token following the statement (if the statement has a terminator, this is
70084  *  the token after the terminator).
70085  */
70086 
70087 #define DUK__HAS_VAL                  (1 << 0)  /* stmt has non-empty value */
70088 #define DUK__HAS_TERM                 (1 << 1)  /* stmt has explicit/implicit semicolon terminator */
70089 #define DUK__ALLOW_AUTO_SEMI_ALWAYS   (1 << 2)  /* allow automatic semicolon even without lineterm (compatibility) */
70090 #define DUK__STILL_PROLOGUE           (1 << 3)  /* statement does not terminate directive prologue */
70091 #define DUK__IS_TERMINAL              (1 << 4)  /* statement is guaranteed to be terminal (control doesn't flow to next statement) */
70092 
70093 /* Parse a single variable declaration (e.g. "i" or "i=10").  A leading 'var'
70094  * has already been eaten.  These is no return value in 'res', it is used only
70095  * as a temporary.
70096  *
70097  * When called from 'for-in' statement parser, the initializer expression must
70098  * not allow the 'in' token.  The caller supply additional expression parsing
70099  * flags (like DUK__EXPR_FLAG_REJECT_IN) in 'expr_flags'.
70100  *
70101  * Finally, out_rc_varname and out_reg_varbind are updated to reflect where
70102  * the identifier is bound:
70103  *
70104  *    If register bound:      out_reg_varbind >= 0, out_rc_varname == 0 (ignore)
70105  *    If not register bound:  out_reg_varbind < 0, out_rc_varname >= 0
70106  *
70107  * These allow the caller to use the variable for further assignment, e.g.
70108  * as is done in 'for-in' parsing.
70109  */
70110 
70111 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) {
70112 	duk_hthread *thr = comp_ctx->thr;
70113 	duk_hstring *h_varname;
70114 	duk_regconst_t reg_varbind;
70115 	duk_regconst_t rc_varname;
70116 
70117 	/* assume 'var' has been eaten */
70118 
70119 	/* Note: Identifier rejects reserved words */
70120 	if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
70121 		goto syntax_error;
70122 	}
70123 	h_varname = comp_ctx->curr_token.str1;
70124 
70125 	DUK_ASSERT(h_varname != NULL);
70126 
70127 	/* strict mode restrictions (E5 Section 12.2.1) */
70128 	if (duk__hstring_is_eval_or_arguments_in_strict_mode(comp_ctx, h_varname)) {
70129 		goto syntax_error;
70130 	}
70131 
70132 	/* register declarations in first pass */
70133 	if (comp_ctx->curr_func.in_scanning) {
70134 		duk_uarridx_t n;
70135 		DUK_DDD(DUK_DDDPRINT("register variable declaration %!O in pass 1",
70136 		                     (duk_heaphdr *) h_varname));
70137 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
70138 		duk_push_hstring(thr, h_varname);
70139 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
70140 		duk_push_int(thr, DUK_DECL_TYPE_VAR + (0 << 8));
70141 		duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
70142 	}
70143 
70144 	duk_push_hstring(thr, h_varname);  /* push before advancing to keep reachable */
70145 
70146 	/* register binding lookup is based on varmap (even in first pass) */
70147 	duk_dup_top(thr);
70148 	(void) duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname);
70149 
70150 	duk__advance(comp_ctx);  /* eat identifier */
70151 
70152 	if (comp_ctx->curr_token.t == DUK_TOK_EQUALSIGN) {
70153 		duk__advance(comp_ctx);
70154 
70155 		DUK_DDD(DUK_DDDPRINT("vardecl, assign to '%!O' -> reg_varbind=%ld, rc_varname=%ld",
70156 		                     (duk_heaphdr *) h_varname, (long) reg_varbind, (long) rc_varname));
70157 
70158 		duk__exprtop(comp_ctx, res, DUK__BP_COMMA | expr_flags /*rbp_flags*/);  /* AssignmentExpression */
70159 
70160 		if (reg_varbind >= 0) {
70161 			duk__ivalue_toforcedreg(comp_ctx, res, reg_varbind);
70162 		} else {
70163 			duk_regconst_t reg_val;
70164 			reg_val = duk__ivalue_toreg(comp_ctx, res);
70165 			duk__emit_a_bc(comp_ctx,
70166 			               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70167 			               reg_val,
70168 			               rc_varname);
70169 		}
70170 	} else {
70171 		if (expr_flags & DUK__EXPR_FLAG_REQUIRE_INIT) {
70172 			/* Used for minimal 'const': initializer required. */
70173 			goto syntax_error;
70174 		}
70175 	}
70176 
70177 	duk_pop(thr);  /* pop varname */
70178 
70179 	*out_rc_varname = rc_varname;
70180 	*out_reg_varbind = reg_varbind;
70181 
70182 	return;
70183 
70184  syntax_error:
70185 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_VAR_DECLARATION);
70186 	DUK_WO_NORETURN(return;);
70187 }
70188 
70189 DUK_LOCAL void duk__parse_var_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_small_uint_t expr_flags) {
70190 	duk_regconst_t reg_varbind;
70191 	duk_regconst_t rc_varname;
70192 
70193 	duk__advance(comp_ctx);  /* eat 'var' */
70194 
70195 	for (;;) {
70196 		/* rc_varname and reg_varbind are ignored here */
70197 		duk__parse_var_decl(comp_ctx, res, 0 | expr_flags, &reg_varbind, &rc_varname);
70198 
70199 		if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70200 			break;
70201 		}
70202 		duk__advance(comp_ctx);
70203 	}
70204 }
70205 
70206 DUK_LOCAL void duk__parse_for_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70207 	duk_hthread *thr = comp_ctx->thr;
70208 	duk_int_t pc_v34_lhs;         /* start variant 3/4 left-hand-side code (L1 in doc/compiler.rst example) */
70209 	duk_regconst_t temp_reset;    /* knock back "next temp" to this whenever possible */
70210 	duk_regconst_t reg_temps;     /* preallocated temporaries (2) for variants 3 and 4 */
70211 
70212 	DUK_DDD(DUK_DDDPRINT("start parsing a for/for-in statement"));
70213 
70214 	/* Two temporaries are preallocated here for variants 3 and 4 which need
70215 	 * registers which are never clobbered by expressions in the loop
70216 	 * (concretely: for the enumerator object and the next enumerated value).
70217 	 * Variants 1 and 2 "release" these temps.
70218 	 */
70219 
70220 	reg_temps = DUK__ALLOCTEMPS(comp_ctx, 2);
70221 
70222 	temp_reset = DUK__GETTEMP(comp_ctx);
70223 
70224 	/*
70225 	 *  For/for-in main variants are:
70226 	 *
70227 	 *    1. for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement
70228 	 *    2. for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement
70229 	 *    3. for (LeftHandSideExpression in Expression) Statement
70230 	 *    4. for (var VariableDeclarationNoIn in Expression) Statement
70231 	 *
70232 	 *  Parsing these without arbitrary lookahead or backtracking is relatively
70233 	 *  tricky but we manage to do so for now.
70234 	 *
70235 	 *  See doc/compiler.rst for a detailed discussion of control flow
70236 	 *  issues, evaluation order issues, etc.
70237 	 */
70238 
70239 	duk__advance(comp_ctx);  /* eat 'for' */
70240 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70241 
70242 	DUK_DDD(DUK_DDDPRINT("detecting for/for-in loop variant, pc=%ld", (long) duk__get_current_pc(comp_ctx)));
70243 
70244 	/* a label site has been emitted by duk__parse_stmt() automatically
70245 	 * (it will also emit the ENDLABEL).
70246 	 */
70247 
70248 	if (comp_ctx->curr_token.t == DUK_TOK_VAR) {
70249 		/*
70250 		 *  Variant 2 or 4
70251 		 */
70252 
70253 		duk_regconst_t reg_varbind;  /* variable binding register if register-bound (otherwise < 0) */
70254 		duk_regconst_t rc_varname;   /* variable name reg/const, if variable not register-bound */
70255 
70256 		duk__advance(comp_ctx);  /* eat 'var' */
70257 		duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70258 		DUK__SETTEMP(comp_ctx, temp_reset);
70259 
70260 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70261 			/*
70262 			 *  Variant 4
70263 			 */
70264 
70265 			DUK_DDD(DUK_DDDPRINT("detected for variant 4: for (var VariableDeclarationNoIn in Expression) Statement"));
70266 			pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here */
70267 			if (reg_varbind >= 0) {
70268 				duk__emit_a_bc(comp_ctx,
70269 				               DUK_OP_LDREG,
70270 				               reg_varbind,
70271 				               reg_temps + 0);
70272 			} else {
70273 				duk__emit_a_bc(comp_ctx,
70274 				               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70275 				               reg_temps + 0,
70276 				               rc_varname);
70277 			}
70278 			goto parse_3_or_4;
70279 		} else {
70280 			/*
70281 			 *  Variant 2
70282 			 */
70283 
70284 			DUK_DDD(DUK_DDDPRINT("detected for variant 2: for (var VariableDeclarationNoIn; Expression_opt; Expression_opt) Statement"));
70285 			for (;;) {
70286 				/* more initializers */
70287 				if (comp_ctx->curr_token.t != DUK_TOK_COMMA) {
70288 					break;
70289 				}
70290 				DUK_DDD(DUK_DDDPRINT("variant 2 has another variable initializer"));
70291 
70292 				duk__advance(comp_ctx);  /* eat comma */
70293 				duk__parse_var_decl(comp_ctx, res, DUK__EXPR_FLAG_REJECT_IN, &reg_varbind, &rc_varname);
70294 			}
70295 			goto parse_1_or_2;
70296 		}
70297 	} else {
70298 		/*
70299 		 *  Variant 1 or 3
70300 		 */
70301 
70302 		pc_v34_lhs = duk__get_current_pc(comp_ctx);  /* jump is inserted here (variant 3) */
70303 
70304 		/* Note that duk__exprtop() here can clobber any reg above current temp_next,
70305 		 * so any loop variables (e.g. enumerator) must be "preallocated".
70306 		 */
70307 
70308 		/* don't coerce yet to a plain value (variant 3 needs special handling) */
70309 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_REJECT_IN | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression */
70310 		if (comp_ctx->curr_token.t == DUK_TOK_IN) {
70311 			/*
70312 			 *  Variant 3
70313 			 */
70314 
70315 			/* XXX: need to determine LHS type, and check that it is LHS compatible */
70316 			DUK_DDD(DUK_DDDPRINT("detected for variant 3: for (LeftHandSideExpression in Expression) Statement"));
70317 			if (duk__expr_is_empty(comp_ctx)) {
70318 				goto syntax_error;  /* LeftHandSideExpression does not allow empty expression */
70319 			}
70320 
70321 			if (res->t == DUK_IVAL_VAR) {
70322 				duk_regconst_t reg_varbind;
70323 				duk_regconst_t rc_varname;
70324 
70325 				duk_dup(thr, res->x1.valstack_idx);
70326 				if (duk__lookup_lhs(comp_ctx, &reg_varbind, &rc_varname)) {
70327 					duk__emit_a_bc(comp_ctx,
70328 					               DUK_OP_LDREG,
70329 					               reg_varbind,
70330 					               reg_temps + 0);
70331 				} else {
70332 					duk__emit_a_bc(comp_ctx,
70333 					               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
70334 					               reg_temps + 0,
70335 					               rc_varname);
70336 				}
70337 			} else if (res->t == DUK_IVAL_PROP) {
70338 				/* Don't allow a constant for the object (even for a number etc), as
70339 				 * it goes into the 'A' field of the opcode.
70340 				 */
70341 				duk_regconst_t reg_obj;
70342 				duk_regconst_t rc_key;
70343 				reg_obj = duk__ispec_toregconst_raw(comp_ctx, &res->x1, -1 /*forced_reg*/, 0 /*flags*/);  /* don't allow const */
70344 				rc_key = duk__ispec_toregconst_raw(comp_ctx, &res->x2, -1 /*forced_reg*/, DUK__IVAL_FLAG_ALLOW_CONST /*flags*/);
70345 				duk__emit_a_b_c(comp_ctx,
70346 				                DUK_OP_PUTPROP | DUK__EMIT_FLAG_A_IS_SOURCE | DUK__EMIT_FLAG_BC_REGCONST,
70347 				                reg_obj,
70348 				                rc_key,
70349 				                reg_temps + 0);
70350 			} else {
70351 				duk__ivalue_toplain_ignore(comp_ctx, res);  /* just in case */
70352 				duk__emit_op_only(comp_ctx,
70353 				                  DUK_OP_INVLHS);
70354 			}
70355 			goto parse_3_or_4;
70356 		} else {
70357 			/*
70358 			 *  Variant 1
70359 			 */
70360 
70361 			DUK_DDD(DUK_DDDPRINT("detected for variant 1: for (ExpressionNoIn_opt; Expression_opt; Expression_opt) Statement"));
70362 			duk__ivalue_toplain_ignore(comp_ctx, res);
70363 			goto parse_1_or_2;
70364 		}
70365 	}
70366 
70367  parse_1_or_2:
70368 	/*
70369 	 *  Parse variant 1 or 2.  The first part expression (which differs
70370 	 *  in the variants) has already been parsed and its code emitted.
70371 	 *
70372 	 *  reg_temps + 0: unused
70373 	 *  reg_temps + 1: unused
70374 	 */
70375 	{
70376 		duk_regconst_t rc_cond;
70377 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4;
70378 		duk_int_t pc_jumpto_l3, pc_jumpto_l4;
70379 		duk_bool_t expr_c_empty;
70380 
70381 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 1 and 2"));
70382 
70383 		/* "release" preallocated temps since we won't need them */
70384 		temp_reset = reg_temps + 0;
70385 		DUK__SETTEMP(comp_ctx, temp_reset);
70386 
70387 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
70388 
70389 		pc_l1 = duk__get_current_pc(comp_ctx);
70390 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
70391 		if (duk__expr_is_empty(comp_ctx)) {
70392 			/* no need to coerce */
70393 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
70394 			pc_jumpto_l4 = -1;  /* omitted */
70395 		} else {
70396 			rc_cond = duk__ivalue_toregconst(comp_ctx, res);
70397 			duk__emit_if_false_skip(comp_ctx, rc_cond);
70398 			pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* to body */
70399 			pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);  /* to exit */
70400 		}
70401 		DUK__SETTEMP(comp_ctx, temp_reset);
70402 
70403 		duk__advance_expect(comp_ctx, DUK_TOK_SEMICOLON);
70404 
70405 		pc_l2 = duk__get_current_pc(comp_ctx);
70406 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR | DUK__EXPR_FLAG_ALLOW_EMPTY /*rbp_flags*/);  /* Expression_opt */
70407 		if (duk__expr_is_empty(comp_ctx)) {
70408 			/* no need to coerce */
70409 			expr_c_empty = 1;
70410 			/* JUMP L1 omitted */
70411 		} else {
70412 			duk__ivalue_toplain_ignore(comp_ctx, res);
70413 			expr_c_empty = 0;
70414 			duk__emit_jump(comp_ctx, pc_l1);
70415 		}
70416 		DUK__SETTEMP(comp_ctx, temp_reset);
70417 
70418 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
70419 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70420 
70421 		pc_l3 = duk__get_current_pc(comp_ctx);
70422 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70423 		if (expr_c_empty) {
70424 			duk__emit_jump(comp_ctx, pc_l1);
70425 		} else {
70426 			duk__emit_jump(comp_ctx, pc_l2);
70427 		}
70428 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
70429 
70430 		pc_l4 = duk__get_current_pc(comp_ctx);
70431 
70432 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l3: %ld->%ld, jumpto_l4: %ld->%ld, "
70433 		                     "break: %ld->%ld, continue: %ld->%ld",
70434 			             (long) pc_jumpto_l3, (long) pc_l3, (long) pc_jumpto_l4, (long) pc_l4,
70435 		                     (long) (pc_label_site + 1), (long) pc_l4, (long) (pc_label_site + 2), (long) pc_l2));
70436 
70437 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
70438 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
70439 		duk__patch_jump(comp_ctx,
70440 		                pc_label_site + 1,
70441 		                pc_l4);                         /* break jump */
70442 		duk__patch_jump(comp_ctx,
70443 		                pc_label_site + 2,
70444 		                expr_c_empty ? pc_l1 : pc_l2);  /* continue jump */
70445 	}
70446 	goto finished;
70447 
70448  parse_3_or_4:
70449 	/*
70450 	 *  Parse variant 3 or 4.
70451 	 *
70452 	 *  For variant 3 (e.g. "for (A in C) D;") the code for A (except the
70453 	 *  final property/variable write) has already been emitted.  The first
70454 	 *  instruction of that code is at pc_v34_lhs; a JUMP needs to be inserted
70455 	 *  there to satisfy control flow needs.
70456 	 *
70457 	 *  For variant 4, if the variable declaration had an initializer
70458 	 *  (e.g. "for (var A = B in C) D;") the code for the assignment
70459 	 *  (B) has already been emitted.
70460 	 *
70461 	 *  Variables set before entering here:
70462 	 *
70463 	 *    pc_v34_lhs:    insert a "JUMP L2" here (see doc/compiler.rst example).
70464 	 *    reg_temps + 0: iteration target value (written to LHS)
70465 	 *    reg_temps + 1: enumerator object
70466 	 */
70467 	{
70468 		duk_int_t pc_l1, pc_l2, pc_l3, pc_l4, pc_l5;
70469 		duk_int_t pc_jumpto_l2, pc_jumpto_l3, pc_jumpto_l4, pc_jumpto_l5;
70470 		duk_regconst_t reg_target;
70471 
70472 		DUK_DDD(DUK_DDDPRINT("shared code for parsing variants 3 and 4, pc_v34_lhs=%ld", (long) pc_v34_lhs));
70473 
70474 		DUK__SETTEMP(comp_ctx, temp_reset);
70475 
70476 		/* First we need to insert a jump in the middle of previously
70477 		 * emitted code to get the control flow right.  No jumps can
70478 		 * cross the position where the jump is inserted.  See doc/compiler.rst
70479 		 * for discussion on the intricacies of control flow and side effects
70480 		 * for variants 3 and 4.
70481 		 */
70482 
70483 		duk__insert_jump_entry(comp_ctx, pc_v34_lhs);
70484 		pc_jumpto_l2 = pc_v34_lhs;  /* inserted jump */
70485 		pc_l1 = pc_v34_lhs + 1;     /* +1, right after inserted jump */
70486 
70487 		/* The code for writing reg_temps + 0 to the left hand side has already
70488 		 * been emitted.
70489 		 */
70490 
70491 		pc_jumpto_l3 = duk__emit_jump_empty(comp_ctx);  /* -> loop body */
70492 
70493 		duk__advance(comp_ctx);  /* eat 'in' */
70494 
70495 		/* Parse enumeration target and initialize enumerator.  For 'null' and 'undefined',
70496 		 * INITENUM will creates a 'null' enumerator which works like an empty enumerator
70497 		 * (E5 Section 12.6.4, step 3).  Note that INITENUM requires the value to be in a
70498 		 * register (constant not allowed).
70499 		 */
70500 
70501 		pc_l2 = duk__get_current_pc(comp_ctx);
70502 		reg_target = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);  /* Expression */
70503 		duk__emit_b_c(comp_ctx,
70504 		              DUK_OP_INITENUM | DUK__EMIT_FLAG_B_IS_TARGET,
70505 		              reg_temps + 1,
70506 		              reg_target);
70507 		pc_jumpto_l4 = duk__emit_jump_empty(comp_ctx);
70508 		DUK__SETTEMP(comp_ctx, temp_reset);
70509 
70510 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
70511 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70512 
70513 		pc_l3 = duk__get_current_pc(comp_ctx);
70514 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70515 		/* temp reset is not necessary after duk__parse_stmt(), which already does it */
70516 
70517 		/* NEXTENUM needs a jump slot right after the main opcode.
70518 		 * We need the code emitter to reserve the slot: if there's
70519 		 * target shuffling, the target shuffle opcodes must happen
70520 		 * after the jump slot (for NEXTENUM the shuffle opcodes are
70521 		 * not needed if the enum is finished).
70522 		 */
70523 		pc_l4 = duk__get_current_pc(comp_ctx);
70524 		duk__emit_b_c(comp_ctx,
70525 		              DUK_OP_NEXTENUM | DUK__EMIT_FLAG_B_IS_TARGET | DUK__EMIT_FLAG_RESERVE_JUMPSLOT,
70526 		              reg_temps + 0,
70527 		              reg_temps + 1);
70528 		pc_jumpto_l5 = comp_ctx->emit_jumpslot_pc;  /* NEXTENUM jump slot: executed when enum finished */
70529 		duk__emit_jump(comp_ctx, pc_l1);  /* jump to next loop, using reg_v34_iter as iterated value */
70530 
70531 		pc_l5 = duk__get_current_pc(comp_ctx);
70532 
70533 		/* XXX: since the enumerator may be a memory expensive object,
70534 		 * perhaps clear it explicitly here?  If so, break jump must
70535 		 * go through this clearing operation.
70536 		 */
70537 
70538 		DUK_DDD(DUK_DDDPRINT("patching jumps: jumpto_l2: %ld->%ld, jumpto_l3: %ld->%ld, "
70539 		                     "jumpto_l4: %ld->%ld, jumpto_l5: %ld->%ld, "
70540 		                     "break: %ld->%ld, continue: %ld->%ld",
70541 			             (long) pc_jumpto_l2, (long) pc_l2, (long) pc_jumpto_l3, (long) pc_l3,
70542 			             (long) pc_jumpto_l4, (long) pc_l4, (long) pc_jumpto_l5, (long) pc_l5,
70543 		                     (long) (pc_label_site + 1), (long) pc_l5, (long) (pc_label_site + 2), (long) pc_l4));
70544 
70545 		duk__patch_jump(comp_ctx, pc_jumpto_l2, pc_l2);
70546 		duk__patch_jump(comp_ctx, pc_jumpto_l3, pc_l3);
70547 		duk__patch_jump(comp_ctx, pc_jumpto_l4, pc_l4);
70548 		duk__patch_jump(comp_ctx, pc_jumpto_l5, pc_l5);
70549 		duk__patch_jump(comp_ctx, pc_label_site + 1, pc_l5);  /* break jump */
70550 		duk__patch_jump(comp_ctx, pc_label_site + 2, pc_l4);  /* continue jump */
70551 	}
70552 	goto finished;
70553 
70554  finished:
70555 	DUK_DDD(DUK_DDDPRINT("end parsing a for/for-in statement"));
70556 	return;
70557 
70558  syntax_error:
70559 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FOR);
70560 	DUK_WO_NORETURN(return;);
70561 }
70562 
70563 DUK_LOCAL void duk__parse_switch_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70564 	duk_hthread *thr = comp_ctx->thr;
70565 	duk_regconst_t temp_at_loop;
70566 	duk_regconst_t rc_switch;    /* reg/const for switch value */
70567 	duk_regconst_t rc_case;      /* reg/const for case value */
70568 	duk_regconst_t reg_temp;     /* general temp register */
70569 	duk_int_t pc_prevcase = -1;
70570 	duk_int_t pc_prevstmt = -1;
70571 	duk_int_t pc_default = -1;   /* -1 == not set, -2 == pending (next statement list) */
70572 
70573 	/* Note: negative pc values are ignored when patching jumps, so no explicit checks needed */
70574 
70575 	/*
70576 	 *  Switch is pretty complicated because of several conflicting concerns:
70577 	 *
70578 	 *    - Want to generate code without an intermediate representation,
70579 	 *      i.e., in one go
70580 	 *
70581 	 *    - Case selectors are expressions, not values, and may thus e.g. throw
70582 	 *      exceptions (which causes evaluation order concerns)
70583 	 *
70584 	 *    - Evaluation semantics of case selectors and default clause need to be
70585 	 *      carefully implemented to provide correct behavior even with case value
70586 	 *      side effects
70587 	 *
70588 	 *    - Fall through case and default clauses; avoiding dead JUMPs if case
70589 	 *      ends with an unconditional jump (a break or a continue)
70590 	 *
70591 	 *    - The same case value may occur multiple times, but evaluation rules
70592 	 *      only process the first match before switching to a "propagation" mode
70593 	 *      where case values are no longer evaluated
70594 	 *
70595 	 *  See E5 Section 12.11.  Also see doc/compiler.rst for compilation
70596 	 *  discussion.
70597 	 */
70598 
70599 	duk__advance(comp_ctx);
70600 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70601 	rc_switch = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70602 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* RegExp mode does not matter. */
70603 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
70604 
70605 	DUK_DDD(DUK_DDDPRINT("switch value in register %ld", (long) rc_switch));
70606 
70607 	temp_at_loop = DUK__GETTEMP(comp_ctx);
70608 
70609 	for (;;) {
70610 		duk_int_t num_stmts;
70611 		duk_small_uint_t tok;
70612 
70613 		/* sufficient for keeping temp reg numbers in check */
70614 		DUK__SETTEMP(comp_ctx, temp_at_loop);
70615 
70616 		if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
70617 			break;
70618 		}
70619 
70620 		/*
70621 		 *  Parse a case or default clause.
70622 		 */
70623 
70624 		if (comp_ctx->curr_token.t == DUK_TOK_CASE) {
70625 			/*
70626 			 *  Case clause.
70627 			 *
70628 			 *  Note: cannot use reg_case as a temp register (for SEQ target)
70629 			 *  because it may be a constant.
70630 			 */
70631 
70632 			duk__patch_jump_here(comp_ctx, pc_prevcase);  /* chain jumps for case
70633 			                                               * evaluation and checking
70634 			                                               */
70635 
70636 			duk__advance(comp_ctx);
70637 			rc_case = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70638 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
70639 
70640 			reg_temp = DUK__ALLOCTEMP(comp_ctx);
70641 			duk__emit_a_b_c(comp_ctx,
70642 			                DUK_OP_SEQ | DUK__EMIT_FLAG_BC_REGCONST,
70643 			                reg_temp,
70644 			                rc_switch,
70645 			                rc_case);
70646 			duk__emit_if_true_skip(comp_ctx, reg_temp);
70647 
70648 			/* jump to next case clause */
70649 			pc_prevcase = duk__emit_jump_empty(comp_ctx);  /* no match, next case */
70650 
70651 			/* statements go here (if any) on next loop */
70652 		} else if (comp_ctx->curr_token.t == DUK_TOK_DEFAULT) {
70653 			/*
70654 			 *  Default clause.
70655 			 */
70656 
70657 			if (pc_default >= 0) {
70658 				goto syntax_error;
70659 			}
70660 			duk__advance(comp_ctx);
70661 			duk__advance_expect(comp_ctx, DUK_TOK_COLON);
70662 
70663 			/* Fix for https://github.com/svaarala/duktape/issues/155:
70664 			 * If 'default' is first clause (detected by pc_prevcase < 0)
70665 			 * we need to ensure we stay in the matching chain.
70666 			 */
70667 			if (pc_prevcase < 0) {
70668 				DUK_DD(DUK_DDPRINT("default clause is first, emit prevcase jump"));
70669 				pc_prevcase = duk__emit_jump_empty(comp_ctx);
70670 			}
70671 
70672 			/* default clause matches next statement list (if any) */
70673 			pc_default = -2;
70674 		} else {
70675 			/* Code is not accepted before the first case/default clause */
70676 			goto syntax_error;
70677 		}
70678 
70679 		/*
70680 		 *  Parse code after the clause.  Possible terminators are
70681 		 *  'case', 'default', and '}'.
70682 		 *
70683 		 *  Note that there may be no code at all, not even an empty statement,
70684 		 *  between case clauses.  This must be handled just like an empty statement
70685 		 *  (omitting seemingly pointless JUMPs), to avoid situations like
70686 		 *  test-bug-case-fallthrough.js.
70687 		 */
70688 
70689 		num_stmts = 0;
70690 		if (pc_default == -2) {
70691 			pc_default = duk__get_current_pc(comp_ctx);
70692 		}
70693 
70694 		/* Note: this is correct even for default clause statements:
70695 		 * they participate in 'fall-through' behavior even if the
70696 		 * default clause is in the middle.
70697 		 */
70698 		duk__patch_jump_here(comp_ctx, pc_prevstmt);  /* chain jumps for 'fall-through'
70699 		                                               * after a case matches.
70700 		                                               */
70701 
70702 		for (;;) {
70703 			tok = comp_ctx->curr_token.t;
70704 			if (tok == DUK_TOK_CASE || tok == DUK_TOK_DEFAULT ||
70705 			    tok == DUK_TOK_RCURLY) {
70706 				break;
70707 			}
70708 			num_stmts++;
70709 			duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70710 		}
70711 
70712 		/* fall-through jump to next code of next case (backpatched) */
70713 		pc_prevstmt = duk__emit_jump_empty(comp_ctx);
70714 
70715 		/* XXX: would be nice to omit this jump when the jump is not
70716 		 * reachable, at least in the obvious cases (such as the case
70717 		 * ending with a 'break'.
70718 		 *
70719 		 * Perhaps duk__parse_stmt() could provide some info on whether
70720 		 * the statement is a "dead end"?
70721 		 *
70722 		 * If implemented, just set pc_prevstmt to -1 when not needed.
70723 		 */
70724 	}
70725 
70726 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
70727 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70728 	duk__advance(comp_ctx);  /* Allow RegExp as part of next stmt. */
70729 
70730 	/* default case control flow patchup; note that if pc_prevcase < 0
70731 	 * (i.e. no case clauses), control enters default case automatically.
70732 	 */
70733 	if (pc_default >= 0) {
70734 		/* default case exists: go there if no case matches */
70735 		duk__patch_jump(comp_ctx, pc_prevcase, pc_default);
70736 	} else {
70737 		/* default case does not exist, or no statements present
70738 		 * after default case: finish case evaluation
70739 		 */
70740 		duk__patch_jump_here(comp_ctx, pc_prevcase);
70741 	}
70742 
70743 	/* fall-through control flow patchup; note that pc_prevstmt may be
70744 	 * < 0 (i.e. no case clauses), in which case this is a no-op.
70745 	 */
70746 	duk__patch_jump_here(comp_ctx, pc_prevstmt);
70747 
70748 	/* continue jump not patched, an INVALID opcode remains there */
70749 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70750 
70751 	/* Note: 'fast' breaks will jump to pc_label_site + 1, which will
70752 	 * then jump here.  The double jump will be eliminated by a
70753 	 * peephole pass, resulting in an optimal jump here.  The label
70754 	 * site jumps will remain in bytecode and will waste code size.
70755 	 */
70756 
70757 	return;
70758 
70759  syntax_error:
70760 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_SWITCH);
70761 	DUK_WO_NORETURN(return;);
70762 }
70763 
70764 DUK_LOCAL void duk__parse_if_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70765 	duk_regconst_t temp_reset;
70766 	duk_regconst_t rc_cond;
70767 	duk_int_t pc_jump_false;
70768 
70769 	DUK_DDD(DUK_DDDPRINT("begin parsing if statement"));
70770 
70771 	temp_reset = DUK__GETTEMP(comp_ctx);
70772 
70773 	duk__advance(comp_ctx);  /* eat 'if' */
70774 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70775 
70776 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70777 	duk__emit_if_true_skip(comp_ctx, rc_cond);
70778 	pc_jump_false = duk__emit_jump_empty(comp_ctx);  /* jump to end or else part */
70779 	DUK__SETTEMP(comp_ctx, temp_reset);
70780 
70781 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70782 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70783 
70784 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70785 
70786 	/* The 'else' ambiguity is resolved by 'else' binding to the innermost
70787 	 * construct, so greedy matching is correct here.
70788 	 */
70789 
70790 	if (comp_ctx->curr_token.t == DUK_TOK_ELSE) {
70791 		duk_int_t pc_jump_end;
70792 
70793 		DUK_DDD(DUK_DDDPRINT("if has else part"));
70794 
70795 		duk__advance(comp_ctx);
70796 
70797 		pc_jump_end = duk__emit_jump_empty(comp_ctx);  /* jump from true part to end */
70798 		duk__patch_jump_here(comp_ctx, pc_jump_false);
70799 
70800 		duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70801 
70802 		duk__patch_jump_here(comp_ctx, pc_jump_end);
70803 	} else {
70804 		DUK_DDD(DUK_DDDPRINT("if does not have else part"));
70805 
70806 		duk__patch_jump_here(comp_ctx, pc_jump_false);
70807 	}
70808 
70809 	DUK_DDD(DUK_DDDPRINT("end parsing if statement"));
70810 }
70811 
70812 DUK_LOCAL void duk__parse_do_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70813 	duk_regconst_t rc_cond;
70814 	duk_int_t pc_start;
70815 
70816 	DUK_DDD(DUK_DDDPRINT("begin parsing do statement"));
70817 
70818 	duk__advance(comp_ctx);  /* Eat 'do'; allow RegExp as part of next stmt. */
70819 
70820 	pc_start = duk__get_current_pc(comp_ctx);
70821 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70822 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
70823 
70824 	duk__advance_expect(comp_ctx, DUK_TOK_WHILE);
70825 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70826 
70827 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70828 	duk__emit_if_false_skip(comp_ctx, rc_cond);
70829 	duk__emit_jump(comp_ctx, pc_start);
70830 	/* no need to reset temps, as we're finished emitting code */
70831 
70832 	comp_ctx->curr_func.allow_regexp_in_adv = 1;  /* Allow RegExp as part of next stmt. */
70833 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
70834 
70835 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70836 
70837 	DUK_DDD(DUK_DDDPRINT("end parsing do statement"));
70838 }
70839 
70840 DUK_LOCAL void duk__parse_while_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_int_t pc_label_site) {
70841 	duk_regconst_t temp_reset;
70842 	duk_regconst_t rc_cond;
70843 	duk_int_t pc_start;
70844 	duk_int_t pc_jump_false;
70845 
70846 	DUK_DDD(DUK_DDDPRINT("begin parsing while statement"));
70847 
70848 	temp_reset = DUK__GETTEMP(comp_ctx);
70849 
70850 	duk__advance(comp_ctx);  /* eat 'while' */
70851 
70852 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
70853 
70854 	pc_start = duk__get_current_pc(comp_ctx);
70855 	duk__patch_jump_here(comp_ctx, pc_label_site + 2);  /* continue jump */
70856 
70857 	rc_cond = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70858 	duk__emit_if_true_skip(comp_ctx, rc_cond);
70859 	pc_jump_false = duk__emit_jump_empty(comp_ctx);
70860 	DUK__SETTEMP(comp_ctx, temp_reset);
70861 
70862 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
70863 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
70864 
70865 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
70866 	duk__emit_jump(comp_ctx, pc_start);
70867 
70868 	duk__patch_jump_here(comp_ctx, pc_jump_false);
70869 	duk__patch_jump_here(comp_ctx, pc_label_site + 1);  /* break jump */
70870 
70871 	DUK_DDD(DUK_DDDPRINT("end parsing while statement"));
70872 }
70873 
70874 DUK_LOCAL void duk__parse_break_or_continue_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70875 	duk_hthread *thr = comp_ctx->thr;
70876 	duk_bool_t is_break = (comp_ctx->curr_token.t == DUK_TOK_BREAK);
70877 	duk_int_t label_id;
70878 	duk_int_t label_catch_depth;
70879 	duk_int_t label_pc;  /* points to LABEL; pc+1 = jump site for break; pc+2 = jump site for continue */
70880 	duk_bool_t label_is_closest;
70881 
70882 	DUK_UNREF(res);
70883 
70884 	duk__advance(comp_ctx);  /* eat 'break' or 'continue' */
70885 
70886 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
70887 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
70888 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
70889 		/* break/continue without label */
70890 
70891 		duk__lookup_active_label(comp_ctx, DUK_HTHREAD_STRING_EMPTY_STRING(thr), is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
70892 	} else if (comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER) {
70893 		/* break/continue with label (label cannot be a reserved word, production is 'Identifier' */
70894 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
70895 		duk__lookup_active_label(comp_ctx, comp_ctx->curr_token.str1, is_break, &label_id, &label_catch_depth, &label_pc, &label_is_closest);
70896 		duk__advance(comp_ctx);
70897 	} else {
70898 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BREAK_CONT_LABEL);
70899 		DUK_WO_NORETURN(return;);
70900 	}
70901 
70902 	/* Use a fast break/continue when possible.  A fast break/continue is
70903 	 * just a jump to the LABEL break/continue jump slot, which then jumps
70904 	 * to an appropriate place (for break, going through ENDLABEL correctly).
70905 	 * The peephole optimizer will optimize the jump to a direct one.
70906 	 */
70907 
70908 	if (label_catch_depth == comp_ctx->curr_func.catch_depth &&
70909 	    label_is_closest) {
70910 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
70911 		                     "label_catch_depth=%ld, catch_depth=%ld "
70912 		                     "-> use fast variant (direct jump)",
70913 		                     (long) is_break, (long) label_id, (long) label_is_closest,
70914 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
70915 
70916 		duk__emit_jump(comp_ctx, label_pc + (is_break ? 1 : 2));
70917 	} else {
70918 		DUK_DDD(DUK_DDDPRINT("break/continue: is_break=%ld, label_id=%ld, label_is_closest=%ld, "
70919 		                     "label_catch_depth=%ld, catch_depth=%ld "
70920 		                     "-> use slow variant (longjmp)",
70921 		                     (long) is_break, (long) label_id, (long) label_is_closest,
70922 		                     (long) label_catch_depth, (long) comp_ctx->curr_func.catch_depth));
70923 
70924 		duk__emit_bc(comp_ctx,
70925 		             is_break ? DUK_OP_BREAK : DUK_OP_CONTINUE,
70926 		             (duk_regconst_t) label_id);
70927 	}
70928 }
70929 
70930 DUK_LOCAL void duk__parse_return_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
70931 	duk_hthread *thr = comp_ctx->thr;
70932 	duk_regconst_t rc_val;
70933 
70934 	duk__advance(comp_ctx);  /* eat 'return' */
70935 
70936 	/* A 'return' statement is only allowed inside an actual function body,
70937 	 * not as part of eval or global code.
70938 	 */
70939 	if (!comp_ctx->curr_func.is_function) {
70940 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_RETURN);
70941 		DUK_WO_NORETURN(return;);
70942 	}
70943 
70944 	if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON ||  /* explicit semi follows */
70945 	    comp_ctx->curr_token.lineterm ||                /* automatic semi will be inserted */
70946 	    comp_ctx->curr_token.allow_auto_semi) {         /* automatic semi will be inserted */
70947 		DUK_DDD(DUK_DDDPRINT("empty return value -> undefined"));
70948 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
70949 	} else {
70950 		duk_int_t pc_before_expr;
70951 		duk_int_t pc_after_expr;
70952 
70953 		DUK_DDD(DUK_DDDPRINT("return with a value"));
70954 
70955 		DUK_UNREF(pc_before_expr);
70956 		DUK_UNREF(pc_after_expr);
70957 
70958 		pc_before_expr = duk__get_current_pc(comp_ctx);
70959 		rc_val = duk__exprtop_toregconst(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
70960 		pc_after_expr = duk__get_current_pc(comp_ctx);
70961 
70962 		/* Tail call check: if last opcode emitted was CALL, and
70963 		 * the context allows it, add a tailcall flag to the CALL.
70964 		 * This doesn't guarantee that a tail call will be allowed at
70965 		 * runtime, so the RETURN must still be emitted.  (Duktape
70966 		 * 0.10.0 avoided this and simulated a RETURN if a tail call
70967 		 * couldn't be used at runtime; but this didn't work
70968 		 * correctly with a thread yield/resume, see
70969 		 * test-bug-tailcall-thread-yield-resume.js for discussion.)
70970 		 *
70971 		 * In addition to the last opcode being CALL, we also need to
70972 		 * be sure that 'rc_val' is the result register of the CALL.
70973 		 * For instance, for the expression 'return 0, (function ()
70974 		 * { return 1; }), 2' the last opcode emitted is CALL (no
70975 		 * bytecode is emitted for '2') but 'rc_val' indicates
70976 		 * constant '2'.  Similarly if '2' is replaced by a register
70977 		 * bound variable, no opcodes are emitted but tail call would
70978 		 * be incorrect.
70979 		 *
70980 		 * This is tricky and easy to get wrong.  It would be best to
70981 		 * track enough expression metadata to check that 'rc_val' came
70982 		 * from that last CALL instruction.  We don't have that metadata
70983 		 * now, so we check that 'rc_val' is a temporary register result
70984 		 * (not a constant or a register bound variable).  There should
70985 		 * be no way currently for 'rc_val' to be a temporary for an
70986 		 * expression following the CALL instruction without emitting
70987 		 * some opcodes following the CALL.  This proxy check is used
70988 		 * below.
70989 		 *
70990 		 * See: test-bug-comma-expr-gh131.js.
70991 		 *
70992 		 * The non-standard 'caller' property disables tail calls
70993 		 * because they pose some special cases which haven't been
70994 		 * fixed yet.
70995 		 */
70996 
70997 #if defined(DUK_USE_TAILCALL)
70998 		if (comp_ctx->curr_func.catch_depth == 0 &&   /* no catchers */
70999 		    pc_after_expr > pc_before_expr) {         /* at least one opcode emitted */
71000 			duk_compiler_instr *instr;
71001 			duk_instr_t ins;
71002 			duk_small_uint_t op;
71003 
71004 			instr = duk__get_instr_ptr(comp_ctx, pc_after_expr - 1);
71005 			DUK_ASSERT(instr != NULL);
71006 
71007 			ins = instr->ins;
71008 			op = (duk_small_uint_t) DUK_DEC_OP(ins);
71009 			if ((op & ~0x0fU) == DUK_OP_CALL0 &&
71010 			    DUK__ISREG_TEMP(comp_ctx, rc_val) /* see above */) {
71011 				DUK_DDD(DUK_DDDPRINT("return statement detected a tail call opportunity: "
71012 				                     "catch depth is 0, duk__exprtop() emitted >= 1 instructions, "
71013 				                     "and last instruction is a CALL "
71014 				                     "-> change to TAILCALL"));
71015 				ins |= DUK_ENC_OP(DUK_BC_CALL_FLAG_TAILCALL);
71016 				instr->ins = ins;
71017 			}
71018 		}
71019 #endif  /* DUK_USE_TAILCALL */
71020 
71021 		if (DUK__ISREG(rc_val)) {
71022 			duk__emit_bc(comp_ctx, DUK_OP_RETREG, rc_val);
71023 		} else {
71024 			rc_val = DUK__REMOVECONST(rc_val);
71025 			if (duk__const_needs_refcount(comp_ctx, rc_val)) {
71026 				duk__emit_bc(comp_ctx, DUK_OP_RETCONST, rc_val);
71027 			} else {
71028 				duk__emit_bc(comp_ctx, DUK_OP_RETCONSTN, rc_val);
71029 			}
71030 		}
71031 	}
71032 }
71033 
71034 DUK_LOCAL void duk__parse_throw_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71035 	duk_regconst_t reg_val;
71036 
71037 	duk__advance(comp_ctx);  /* eat 'throw' */
71038 
71039 	/* Unlike break/continue, throw statement does not allow an empty value. */
71040 
71041 	if (comp_ctx->curr_token.lineterm) {
71042 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_INVALID_THROW);
71043 		DUK_WO_NORETURN(return;);
71044 	}
71045 
71046 	reg_val = duk__exprtop_toreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71047 	duk__emit_bc(comp_ctx,
71048 	             DUK_OP_THROW,
71049 	             reg_val);
71050 }
71051 
71052 DUK_LOCAL void duk__parse_try_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71053 	duk_hthread *thr = comp_ctx->thr;
71054 	duk_regconst_t reg_catch;      /* reg_catch+0 and reg_catch+1 are reserved for TRYCATCH */
71055 	duk_regconst_t rc_varname = 0;
71056 	duk_small_uint_t trycatch_flags = 0;
71057 	duk_int_t pc_ldconst = -1;
71058 	duk_int_t pc_trycatch = -1;
71059 	duk_int_t pc_catch = -1;
71060 	duk_int_t pc_finally = -1;
71061 
71062 	DUK_UNREF(res);
71063 
71064 	/*
71065 	 *  See the following documentation for discussion:
71066 	 *
71067 	 *    doc/execution.rst: control flow details
71068 	 *
71069 	 *  Try, catch, and finally "parts" are Blocks, not Statements, so
71070 	 *  they must always be delimited by curly braces.  This is unlike e.g.
71071 	 *  the if statement, which accepts any Statement.  This eliminates any
71072 	 *  questions of matching parts of nested try statements.  The Block
71073 	 *  parsing is implemented inline here (instead of calling out).
71074 	 *
71075 	 *  Finally part has a 'let scoped' variable, which requires a few kinks
71076 	 *  here.
71077 	 */
71078 
71079 	comp_ctx->curr_func.catch_depth++;
71080 
71081 	duk__advance(comp_ctx);  /* eat 'try' */
71082 
71083 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71084 
71085 	/* The target for this LDCONST may need output shuffling, but we assume
71086 	 * that 'pc_ldconst' will be the LDCONST that we can patch later.  This
71087 	 * should be the case because there's no input shuffling.  (If there's
71088 	 * no catch clause, this LDCONST will be replaced with a NOP.)
71089 	 */
71090 	pc_ldconst = duk__get_current_pc(comp_ctx);
71091 	duk__emit_a_bc(comp_ctx, DUK_OP_LDCONST, reg_catch, 0 /*patched later*/);
71092 
71093 	pc_trycatch = duk__get_current_pc(comp_ctx);
71094 	duk__emit_invalid(comp_ctx);  /* TRYCATCH, cannot emit now (not enough info) */
71095 	duk__emit_invalid(comp_ctx);  /* jump for 'catch' case */
71096 	duk__emit_invalid(comp_ctx);  /* jump for 'finally' case or end (if no finally) */
71097 
71098 	/* try part */
71099 	duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71100 	duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71101 	/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71102 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71103 
71104 	if (comp_ctx->curr_token.t == DUK_TOK_CATCH) {
71105 		/*
71106 		 *  The catch variable must be updated to reflect the new allocated
71107 		 *  register for the duration of the catch clause.  We need to store
71108 		 *  and restore the original value for the varmap entry (if any).
71109 		 */
71110 
71111 		/*
71112 		 *  Note: currently register bindings must be fixed for the entire
71113 		 *  function.  So, even though the catch variable is in a register
71114 		 *  we know, we must use an explicit environment record and slow path
71115 		 *  accesses to read/write the catch binding to make closures created
71116 		 *  within the catch clause work correctly.  This restriction should
71117 		 *  be fixable (at least in common cases) later.
71118 		 *
71119 		 *  See: test-bug-catch-binding-2.js.
71120 		 *
71121 		 *  XXX: improve to get fast path access to most catch clauses.
71122 		 */
71123 
71124 		duk_hstring *h_var;
71125 		duk_int_t varmap_value;  /* for storing/restoring the varmap binding for catch variable */
71126 
71127 		DUK_DDD(DUK_DDDPRINT("stack top at start of catch clause: %ld", (long) duk_get_top(thr)));
71128 
71129 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_CATCH;
71130 
71131 		pc_catch = duk__get_current_pc(comp_ctx);
71132 
71133 		duk__advance(comp_ctx);
71134 		duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71135 
71136 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
71137 			/* Identifier, i.e. don't allow reserved words */
71138 			goto syntax_error;
71139 		}
71140 		h_var = comp_ctx->curr_token.str1;
71141 		DUK_ASSERT(h_var != NULL);
71142 
71143 		duk_push_hstring(thr, h_var);  /* keep in on valstack, use borrowed ref below */
71144 
71145 		if (comp_ctx->curr_func.is_strict &&
71146 		    ((h_var == DUK_HTHREAD_STRING_EVAL(thr)) ||
71147 		     (h_var == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)))) {
71148 			DUK_DDD(DUK_DDDPRINT("catch identifier 'eval' or 'arguments' in strict mode -> SyntaxError"));
71149 			goto syntax_error;
71150 		}
71151 
71152 		duk_dup_top(thr);
71153 		rc_varname = duk__getconst(comp_ctx);
71154 		DUK_DDD(DUK_DDDPRINT("catch clause, rc_varname=0x%08lx (%ld)",
71155 		                     (unsigned long) rc_varname, (long) rc_varname));
71156 
71157 		duk__advance(comp_ctx);
71158 		duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);
71159 
71160 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71161 
71162 		DUK_DDD(DUK_DDDPRINT("varmap before modifying for catch clause: %!iT",
71163 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71164 
71165 		duk_dup_top(thr);
71166 		duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
71167 		if (duk_is_undefined(thr, -1)) {
71168 			varmap_value = -2;
71169 		} else if (duk_is_null(thr, -1)) {
71170 			varmap_value = -1;
71171 		} else {
71172 			DUK_ASSERT(duk_is_number(thr, -1));
71173 			varmap_value = duk_get_int(thr, -1);
71174 			DUK_ASSERT(varmap_value >= 0);
71175 		}
71176 		duk_pop(thr);
71177 
71178 #if 0
71179 		/* It'd be nice to do something like this - but it doesn't
71180 		 * work for closures created inside the catch clause.
71181 		 */
71182 		duk_dup_top(thr);
71183 		duk_push_int(thr, (duk_int_t) (reg_catch + 0));
71184 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71185 #endif
71186 		duk_dup_top(thr);
71187 		duk_push_null(thr);
71188 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71189 
71190 		duk__emit_a_bc(comp_ctx,
71191 		               DUK_OP_PUTVAR | DUK__EMIT_FLAG_A_IS_SOURCE,
71192 		               reg_catch + 0 /*value*/,
71193 		               rc_varname /*varname*/);
71194 
71195 		DUK_DDD(DUK_DDDPRINT("varmap before parsing catch clause: %!iT",
71196 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71197 
71198 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71199 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71200 
71201 		if (varmap_value == -2) {
71202 			/* not present */
71203 			duk_del_prop(thr, comp_ctx->curr_func.varmap_idx);
71204 		} else {
71205 			if (varmap_value == -1) {
71206 				duk_push_null(thr);
71207 			} else {
71208 				DUK_ASSERT(varmap_value >= 0);
71209 				duk_push_int(thr, varmap_value);
71210 			}
71211 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);
71212 		}
71213 		/* varname is popped by above code */
71214 
71215 		DUK_DDD(DUK_DDDPRINT("varmap after restore catch clause: %!iT",
71216 		                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx)));
71217 
71218 		duk__emit_op_only(comp_ctx,
71219 		                  DUK_OP_ENDCATCH);
71220 
71221 		/*
71222 		 *  XXX: for now, indicate that an expensive catch binding
71223 		 *  declarative environment is always needed.  If we don't
71224 		 *  need it, we don't need the const_varname either.
71225 		 */
71226 
71227 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_CATCH_BINDING;
71228 
71229 		DUK_DDD(DUK_DDDPRINT("stack top at end of catch clause: %ld", (long) duk_get_top(thr)));
71230 	}
71231 
71232 	if (comp_ctx->curr_token.t == DUK_TOK_FINALLY) {
71233 		trycatch_flags |= DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY;
71234 
71235 		pc_finally = duk__get_current_pc(comp_ctx);
71236 
71237 		duk__advance(comp_ctx);
71238 
71239 		duk__advance_expect(comp_ctx, DUK_TOK_LCURLY);
71240 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71241 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71242 		duk__emit_abc(comp_ctx,
71243 		              DUK_OP_ENDFIN,
71244 		              reg_catch);  /* rethrow */
71245 	}
71246 
71247 	if (!(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) &&
71248 	    !(trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY)) {
71249 		/* must have catch and/or finally */
71250 		goto syntax_error;
71251 	}
71252 
71253 	/* If there's no catch block, rc_varname will be 0 and duk__patch_trycatch()
71254 	 * will replace the LDCONST with a NOP.  For any actual constant (including
71255 	 * constant 0) the DUK__CONST_MARKER flag will be set in rc_varname.
71256 	 */
71257 
71258 	duk__patch_trycatch(comp_ctx,
71259 	                    pc_ldconst,
71260 	                    pc_trycatch,
71261 	                    reg_catch,
71262 	                    rc_varname,
71263 	                    trycatch_flags);
71264 
71265 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
71266 		DUK_ASSERT(pc_catch >= 0);
71267 		duk__patch_jump(comp_ctx, pc_trycatch + 1, pc_catch);
71268 	}
71269 
71270 	if (trycatch_flags & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
71271 		DUK_ASSERT(pc_finally >= 0);
71272 		duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finally);
71273 	} else {
71274 		/* without finally, the second jump slot is used to jump to end of stmt */
71275 		duk__patch_jump_here(comp_ctx, pc_trycatch + 2);
71276 	}
71277 
71278 	comp_ctx->curr_func.catch_depth--;
71279 	return;
71280 
71281  syntax_error:
71282 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_TRY);
71283 	DUK_WO_NORETURN(return;);
71284 }
71285 
71286 DUK_LOCAL void duk__parse_with_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res) {
71287 	duk_int_t pc_trycatch;
71288 	duk_int_t pc_finished;
71289 	duk_regconst_t reg_catch;
71290 	duk_small_uint_t trycatch_flags;
71291 
71292 	if (comp_ctx->curr_func.is_strict) {
71293 		DUK_ERROR_SYNTAX(comp_ctx->thr, DUK_STR_WITH_IN_STRICT_MODE);
71294 		DUK_WO_NORETURN(return;);
71295 	}
71296 
71297 	comp_ctx->curr_func.catch_depth++;
71298 
71299 	duk__advance(comp_ctx);  /* eat 'with' */
71300 
71301 	reg_catch = DUK__ALLOCTEMPS(comp_ctx, 2);
71302 
71303 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
71304 	duk__exprtop_toforcedreg(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/, reg_catch);
71305 	comp_ctx->curr_func.allow_regexp_in_adv = 1;
71306 	duk__advance_expect(comp_ctx, DUK_TOK_RPAREN);  /* Allow RegExp as part of next stmt. */
71307 
71308 	pc_trycatch = duk__get_current_pc(comp_ctx);
71309 	trycatch_flags = DUK_BC_TRYCATCH_FLAG_WITH_BINDING;
71310 	duk__emit_a_bc(comp_ctx,
71311 	                DUK_OP_TRYCATCH | DUK__EMIT_FLAG_NO_SHUFFLE_A,
71312 	                (duk_regconst_t) trycatch_flags /*a*/,
71313 	                reg_catch /*bc*/);
71314 	duk__emit_invalid(comp_ctx);  /* catch jump */
71315 	duk__emit_invalid(comp_ctx);  /* finished jump */
71316 
71317 	duk__parse_stmt(comp_ctx, res, 0 /*allow_source_elem*/);
71318 	duk__emit_op_only(comp_ctx, DUK_OP_ENDTRY);
71319 
71320 	pc_finished = duk__get_current_pc(comp_ctx);
71321 
71322 	duk__patch_jump(comp_ctx, pc_trycatch + 2, pc_finished);
71323 
71324 	comp_ctx->curr_func.catch_depth--;
71325 }
71326 
71327 DUK_LOCAL duk_int_t duk__stmt_label_site(duk_compiler_ctx *comp_ctx, duk_int_t label_id) {
71328 	/* if a site already exists, nop: max one label site per statement */
71329 	if (label_id >= 0) {
71330 		return label_id;
71331 	}
71332 
71333 	label_id = comp_ctx->curr_func.label_next++;
71334 	DUK_DDD(DUK_DDDPRINT("allocated new label id for label site: %ld", (long) label_id));
71335 
71336 	duk__emit_bc(comp_ctx,
71337 	             DUK_OP_LABEL,
71338 	             (duk_regconst_t) label_id);
71339 	duk__emit_invalid(comp_ctx);
71340 	duk__emit_invalid(comp_ctx);
71341 
71342 	return label_id;
71343 }
71344 
71345 /* Parse a single statement.
71346  *
71347  * Creates a label site (with an empty label) automatically for iteration
71348  * statements.  Also "peels off" any label statements for explicit labels.
71349  */
71350 DUK_LOCAL void duk__parse_stmt(duk_compiler_ctx *comp_ctx, duk_ivalue *res, duk_bool_t allow_source_elem) {
71351 	duk_hthread *thr = comp_ctx->thr;
71352 	duk_bool_t dir_prol_at_entry;    /* directive prologue status at entry */
71353 	duk_regconst_t temp_at_entry;
71354 	duk_size_t labels_len_at_entry;
71355 	duk_int_t pc_at_entry;           /* assumed to also be PC of "LABEL" */
71356 	duk_int_t stmt_id;
71357 	duk_small_uint_t stmt_flags = 0;
71358 	duk_int_t label_id = -1;
71359 	duk_small_uint_t tok;
71360 	duk_bool_t test_func_decl;
71361 
71362 	DUK__RECURSION_INCREASE(comp_ctx, thr);
71363 
71364 	temp_at_entry = DUK__GETTEMP(comp_ctx);
71365 	pc_at_entry = duk__get_current_pc(comp_ctx);
71366 	labels_len_at_entry = duk_get_length(thr, comp_ctx->curr_func.labelnames_idx);
71367 	stmt_id = comp_ctx->curr_func.stmt_next++;
71368 	dir_prol_at_entry = comp_ctx->curr_func.in_directive_prologue;
71369 
71370 	DUK_UNREF(stmt_id);
71371 
71372 	DUK_DDD(DUK_DDDPRINT("parsing a statement, stmt_id=%ld, temp_at_entry=%ld, labels_len_at_entry=%ld, "
71373 	                     "is_strict=%ld, in_directive_prologue=%ld, catch_depth=%ld",
71374 	                     (long) stmt_id, (long) temp_at_entry, (long) labels_len_at_entry,
71375 	                     (long) comp_ctx->curr_func.is_strict, (long) comp_ctx->curr_func.in_directive_prologue,
71376 	                     (long) comp_ctx->curr_func.catch_depth));
71377 
71378 	/* The directive prologue flag is cleared by default so that it is
71379 	 * unset for any recursive statement parsing.  It is only "revived"
71380 	 * if a directive is detected.  (We could also make directives only
71381 	 * allowed if 'allow_source_elem' was true.)
71382 	 */
71383 	comp_ctx->curr_func.in_directive_prologue = 0;
71384 
71385  retry_parse:
71386 
71387 	DUK_DDD(DUK_DDDPRINT("try stmt parse, stmt_id=%ld, label_id=%ld, allow_source_elem=%ld, catch_depth=%ld",
71388 	                     (long) stmt_id, (long) label_id, (long) allow_source_elem,
71389 	                     (long) comp_ctx->curr_func.catch_depth));
71390 
71391 	/*
71392 	 *  Detect iteration statements; if encountered, establish an
71393 	 *  empty label.
71394 	 */
71395 
71396 	tok = comp_ctx->curr_token.t;
71397 	if (tok == DUK_TOK_FOR || tok == DUK_TOK_DO || tok == DUK_TOK_WHILE ||
71398 	    tok == DUK_TOK_SWITCH) {
71399 		DUK_DDD(DUK_DDDPRINT("iteration/switch statement -> add empty label"));
71400 
71401 		label_id = duk__stmt_label_site(comp_ctx, label_id);
71402 		duk__add_label(comp_ctx,
71403 		               DUK_HTHREAD_STRING_EMPTY_STRING(thr),
71404 		               pc_at_entry /*pc_label*/,
71405 		               label_id);
71406 	}
71407 
71408 	/*
71409 	 *  Main switch for statement / source element type.
71410 	 */
71411 
71412 	switch (comp_ctx->curr_token.t) {
71413 	case DUK_TOK_FUNCTION: {
71414 		/*
71415 		 *  Function declaration, function expression, or (non-standard)
71416 		 *  function statement.
71417 		 *
71418 		 *  The E5 specification only allows function declarations at
71419 		 *  the top level (in "source elements").  An ExpressionStatement
71420 		 *  is explicitly not allowed to begin with a "function" keyword
71421 		 *  (E5 Section 12.4).  Hence any non-error semantics for such
71422 		 *  non-top-level statements are non-standard.  Duktape semantics
71423 		 *  for function statements are modelled after V8, see
71424 		 *  test-dev-func-decl-outside-top.js.
71425 		 */
71426 		test_func_decl = allow_source_elem;
71427 #if defined(DUK_USE_NONSTD_FUNC_STMT)
71428 		/* Lenient: allow function declarations outside top level in
71429 		 * non-strict mode but reject them in strict mode.
71430 		 */
71431 		test_func_decl = test_func_decl || !comp_ctx->curr_func.is_strict;
71432 #endif  /* DUK_USE_NONSTD_FUNC_STMT */
71433 		/* Strict: never allow function declarations outside top level. */
71434 		if (test_func_decl) {
71435 			/* FunctionDeclaration: not strictly a statement but handled as such.
71436 			 *
71437 			 * O(depth^2) parse count for inner functions is handled by recording a
71438 			 * lexer offset on the first compilation pass, so that the function can
71439 			 * be efficiently skipped on the second pass.  This is encapsulated into
71440 			 * duk__parse_func_like_fnum().
71441 			 */
71442 
71443 			duk_int_t fnum;
71444 #if defined(DUK_USE_ASSERTIONS)
71445 			duk_idx_t top_before;
71446 #endif
71447 
71448 			DUK_DDD(DUK_DDDPRINT("function declaration statement"));
71449 
71450 #if defined(DUK_USE_ASSERTIONS)
71451 			top_before = duk_get_top(thr);
71452 #endif
71453 
71454 			duk__advance(comp_ctx);  /* eat 'function' */
71455 			fnum = duk__parse_func_like_fnum(comp_ctx, DUK__FUNC_FLAG_DECL | DUK__FUNC_FLAG_PUSHNAME_PASS1);
71456 
71457 			/* The value stack convention here is a bit odd: the function
71458 			 * name is only pushed on pass 1 (in_scanning), and is needed
71459 			 * to process function declarations.
71460 			 */
71461 			if (comp_ctx->curr_func.in_scanning) {
71462 				duk_uarridx_t n;
71463 
71464 #if defined(DUK_USE_ASSERTIONS)
71465 				DUK_ASSERT(duk_get_top(thr) == top_before + 1);
71466 #endif
71467 				DUK_DDD(DUK_DDDPRINT("register function declaration %!T in pass 1, fnum %ld",
71468 				                     duk_get_tval(thr, -1), (long) fnum));
71469 				n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
71470 				/* funcname is at index -1 */
71471 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n);
71472 				duk_push_int(thr, (duk_int_t) (DUK_DECL_TYPE_FUNC + (fnum << 8)));
71473 				duk_put_prop_index(thr, comp_ctx->curr_func.decls_idx, n + 1);
71474 			} else {
71475 #if defined(DUK_USE_ASSERTIONS)
71476 				DUK_ASSERT(duk_get_top(thr) == top_before);
71477 #endif
71478 			}
71479 
71480 			/* no statement value (unlike function expression) */
71481 			stmt_flags = 0;
71482 			break;
71483 		} else {
71484 			DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_STMT_NOT_ALLOWED);
71485 			DUK_WO_NORETURN(return;);
71486 		}
71487 		break;
71488 	}
71489 	case DUK_TOK_LCURLY: {
71490 		DUK_DDD(DUK_DDDPRINT("block statement"));
71491 		duk__advance(comp_ctx);
71492 		duk__parse_stmts(comp_ctx, 0 /*allow_source_elem*/, 0 /*expect_eof*/, 1 /*regexp_after*/);
71493 		/* the DUK_TOK_RCURLY is eaten by duk__parse_stmts() */
71494 		if (label_id >= 0) {
71495 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71496 		}
71497 		stmt_flags = 0;
71498 		break;
71499 	}
71500 	case DUK_TOK_CONST: {
71501 		DUK_DDD(DUK_DDDPRINT("constant declaration statement"));
71502 		duk__parse_var_stmt(comp_ctx, res, DUK__EXPR_FLAG_REQUIRE_INIT /*expr_flags*/);
71503 		stmt_flags = DUK__HAS_TERM;
71504 		break;
71505 	}
71506 	case DUK_TOK_VAR: {
71507 		DUK_DDD(DUK_DDDPRINT("variable declaration statement"));
71508 		duk__parse_var_stmt(comp_ctx, res, 0 /*expr_flags*/);
71509 		stmt_flags = DUK__HAS_TERM;
71510 		break;
71511 	}
71512 	case DUK_TOK_SEMICOLON: {
71513 		/* empty statement with an explicit semicolon */
71514 		DUK_DDD(DUK_DDDPRINT("empty statement"));
71515 		stmt_flags = DUK__HAS_TERM;
71516 		break;
71517 	}
71518 	case DUK_TOK_IF: {
71519 		DUK_DDD(DUK_DDDPRINT("if statement"));
71520 		duk__parse_if_stmt(comp_ctx, res);
71521 		if (label_id >= 0) {
71522 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71523 		}
71524 		stmt_flags = 0;
71525 		break;
71526 	}
71527 	case DUK_TOK_DO: {
71528 		/*
71529 		 *  Do-while statement is mostly trivial, but there is special
71530 		 *  handling for automatic semicolon handling (triggered by the
71531 		 *  DUK__ALLOW_AUTO_SEMI_ALWAYS) flag related to a bug filed at:
71532 		 *
71533 		 *    https://bugs.ecmascript.org/show_bug.cgi?id=8
71534 		 *
71535 		 *  See doc/compiler.rst for details.
71536 		 */
71537 		DUK_DDD(DUK_DDDPRINT("do statement"));
71538 		DUK_ASSERT(label_id >= 0);
71539 		duk__update_label_flags(comp_ctx,
71540 		                        label_id,
71541 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71542 		duk__parse_do_stmt(comp_ctx, res, pc_at_entry);
71543 		stmt_flags = DUK__HAS_TERM | DUK__ALLOW_AUTO_SEMI_ALWAYS;  /* DUK__ALLOW_AUTO_SEMI_ALWAYS workaround */
71544 		break;
71545 	}
71546 	case DUK_TOK_WHILE: {
71547 		DUK_DDD(DUK_DDDPRINT("while statement"));
71548 		DUK_ASSERT(label_id >= 0);
71549 		duk__update_label_flags(comp_ctx,
71550 		                        label_id,
71551 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71552 		duk__parse_while_stmt(comp_ctx, res, pc_at_entry);
71553 		stmt_flags = 0;
71554 		break;
71555 	}
71556 	case DUK_TOK_FOR: {
71557 		/*
71558 		 *  For/for-in statement is complicated to parse because
71559 		 *  determining the statement type (three-part for vs. a
71560 		 *  for-in) requires potential backtracking.
71561 		 *
71562 		 *  See the helper for the messy stuff.
71563 		 */
71564 		DUK_DDD(DUK_DDDPRINT("for/for-in statement"));
71565 		DUK_ASSERT(label_id >= 0);
71566 		duk__update_label_flags(comp_ctx,
71567 		                        label_id,
71568 		                        DUK_LABEL_FLAG_ALLOW_BREAK | DUK_LABEL_FLAG_ALLOW_CONTINUE);
71569 		duk__parse_for_stmt(comp_ctx, res, pc_at_entry);
71570 		stmt_flags = 0;
71571 		break;
71572 	}
71573 	case DUK_TOK_CONTINUE:
71574 	case DUK_TOK_BREAK: {
71575 		DUK_DDD(DUK_DDDPRINT("break/continue statement"));
71576 		duk__parse_break_or_continue_stmt(comp_ctx, res);
71577 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71578 		break;
71579 	}
71580 	case DUK_TOK_RETURN: {
71581 		DUK_DDD(DUK_DDDPRINT("return statement"));
71582 		duk__parse_return_stmt(comp_ctx, res);
71583 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71584 		break;
71585 	}
71586 	case DUK_TOK_WITH: {
71587 		DUK_DDD(DUK_DDDPRINT("with statement"));
71588 		comp_ctx->curr_func.with_depth++;
71589 		duk__parse_with_stmt(comp_ctx, res);
71590 		if (label_id >= 0) {
71591 			duk__patch_jump_here(comp_ctx, pc_at_entry + 1);  /* break jump */
71592 		}
71593 		comp_ctx->curr_func.with_depth--;
71594 		stmt_flags = 0;
71595 		break;
71596 	}
71597 	case DUK_TOK_SWITCH: {
71598 		/*
71599 		 *  The switch statement is pretty messy to compile.
71600 		 *  See the helper for details.
71601 		 */
71602 		DUK_DDD(DUK_DDDPRINT("switch statement"));
71603 		DUK_ASSERT(label_id >= 0);
71604 		duk__update_label_flags(comp_ctx,
71605 		                        label_id,
71606 		                        DUK_LABEL_FLAG_ALLOW_BREAK);  /* don't allow continue */
71607 		duk__parse_switch_stmt(comp_ctx, res, pc_at_entry);
71608 		stmt_flags = 0;
71609 		break;
71610 	}
71611 	case DUK_TOK_THROW: {
71612 		DUK_DDD(DUK_DDDPRINT("throw statement"));
71613 		duk__parse_throw_stmt(comp_ctx, res);
71614 		stmt_flags = DUK__HAS_TERM | DUK__IS_TERMINAL;
71615 		break;
71616 	}
71617 	case DUK_TOK_TRY: {
71618 		DUK_DDD(DUK_DDDPRINT("try statement"));
71619 		duk__parse_try_stmt(comp_ctx, res);
71620 		stmt_flags = 0;
71621 		break;
71622 	}
71623 	case DUK_TOK_DEBUGGER: {
71624 		duk__advance(comp_ctx);
71625 #if defined(DUK_USE_DEBUGGER_SUPPORT)
71626 		DUK_DDD(DUK_DDDPRINT("debugger statement: debugging enabled, emit debugger opcode"));
71627 		duk__emit_op_only(comp_ctx, DUK_OP_DEBUGGER);
71628 #else
71629 		DUK_DDD(DUK_DDDPRINT("debugger statement: ignored"));
71630 #endif
71631 		stmt_flags = DUK__HAS_TERM;
71632 		break;
71633 	}
71634 	default: {
71635 		/*
71636 		 *  Else, must be one of:
71637 		 *    - ExpressionStatement, possibly a directive (String)
71638 		 *    - LabelledStatement (Identifier followed by ':')
71639 		 *
71640 		 *  Expressions beginning with 'function' keyword are covered by a case
71641 		 *  above (such expressions are not allowed in standard E5 anyway).
71642 		 *  Also expressions starting with '{' are interpreted as block
71643 		 *  statements.  See E5 Section 12.4.
71644 		 *
71645 		 *  Directive detection is tricky; see E5 Section 14.1 on directive
71646 		 *  prologue.  A directive is an expression statement with a single
71647 		 *  string literal and an explicit or automatic semicolon.  Escape
71648 		 *  characters are significant and no parens etc are allowed:
71649 		 *
71650 		 *    'use strict';          // valid 'use strict' directive
71651 		 *    'use\u0020strict';     // valid directive, not a 'use strict' directive
71652 		 *    ('use strict');        // not a valid directive
71653 		 *
71654 		 *  The expression is determined to consist of a single string literal
71655 		 *  based on duk__expr_nud() and duk__expr_led() call counts.  The string literal
71656 		 *  of a 'use strict' directive is determined to lack any escapes based
71657 		 *  num_escapes count from the lexer.  Note that other directives may be
71658 		 *  allowed to contain escapes, so a directive with escapes does not
71659 		 *  terminate a directive prologue.
71660 		 *
71661 		 *  We rely on the fact that the expression parser will not emit any
71662 		 *  code for a single token expression.  However, it will generate an
71663 		 *  intermediate value which we will then successfully ignore.
71664 		 *
71665 		 *  A similar approach is used for labels.
71666 		 */
71667 
71668 		duk_bool_t single_token;
71669 
71670 		DUK_DDD(DUK_DDDPRINT("expression statement"));
71671 		duk__exprtop(comp_ctx, res, DUK__BP_FOR_EXPR /*rbp_flags*/);
71672 
71673 		single_token = (comp_ctx->curr_func.nud_count == 1 &&  /* one token */
71674 		                comp_ctx->curr_func.led_count == 0);   /* no operators */
71675 
71676 		if (single_token &&
71677 		    comp_ctx->prev_token.t == DUK_TOK_IDENTIFIER &&
71678 		    comp_ctx->curr_token.t == DUK_TOK_COLON) {
71679 			/*
71680 			 *  Detected label
71681 			 */
71682 
71683 			duk_hstring *h_lab;
71684 
71685 			/* expected ival */
71686 			DUK_ASSERT(res->t == DUK_IVAL_VAR);
71687 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
71688 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
71689 			h_lab = comp_ctx->prev_token.str1;
71690 			DUK_ASSERT(h_lab != NULL);
71691 
71692 			DUK_DDD(DUK_DDDPRINT("explicit label site for label '%!O'",
71693 			                     (duk_heaphdr *) h_lab));
71694 
71695 			duk__advance(comp_ctx);  /* eat colon */
71696 
71697 			label_id = duk__stmt_label_site(comp_ctx, label_id);
71698 
71699 			duk__add_label(comp_ctx,
71700 			               h_lab,
71701 			               pc_at_entry /*pc_label*/,
71702 			               label_id);
71703 
71704 			/* a statement following a label cannot be a source element
71705 			 * (a function declaration).
71706 			 */
71707 			allow_source_elem = 0;
71708 
71709 			DUK_DDD(DUK_DDDPRINT("label handled, retry statement parsing"));
71710 			goto retry_parse;
71711 		}
71712 
71713 		stmt_flags = 0;
71714 
71715 		if (dir_prol_at_entry &&                           /* still in prologue */
71716 		    single_token &&                                /* single string token */
71717 		    comp_ctx->prev_token.t == DUK_TOK_STRING) {
71718 			/*
71719 			 *  Detected a directive
71720 			 */
71721 			duk_hstring *h_dir;
71722 
71723 			/* expected ival */
71724 			DUK_ASSERT(res->t == DUK_IVAL_PLAIN);
71725 			DUK_ASSERT(res->x1.t == DUK_ISPEC_VALUE);
71726 			DUK_ASSERT(DUK_TVAL_IS_STRING(duk_get_tval(thr, res->x1.valstack_idx)));
71727 			h_dir = comp_ctx->prev_token.str1;
71728 			DUK_ASSERT(h_dir != NULL);
71729 
71730 			DUK_DDD(DUK_DDDPRINT("potential directive: %!O", h_dir));
71731 
71732 			stmt_flags |= DUK__STILL_PROLOGUE;
71733 
71734 			/* Note: escaped characters differentiate directives */
71735 
71736 			if (comp_ctx->prev_token.num_escapes > 0) {
71737 				DUK_DDD(DUK_DDDPRINT("directive contains escapes: valid directive "
71738 				                     "but we ignore such directives"));
71739 			} else {
71740 				/*
71741 				 * The length comparisons are present to handle
71742 				 * strings like "use strict\u0000foo" as required.
71743 				 */
71744 
71745 				if (DUK_HSTRING_GET_BYTELEN(h_dir) == 10 &&
71746 				    DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use strict") == 0) {
71747 #if defined(DUK_USE_STRICT_DECL)
71748 					DUK_DDD(DUK_DDDPRINT("use strict directive detected: strict flag %ld -> %ld",
71749 					                     (long) comp_ctx->curr_func.is_strict, (long) 1));
71750 					comp_ctx->curr_func.is_strict = 1;
71751 #else
71752 					DUK_DDD(DUK_DDDPRINT("use strict detected but strict declarations disabled, ignoring"));
71753 #endif
71754 				} else if (DUK_HSTRING_GET_BYTELEN(h_dir) == 14 &&
71755 				           DUK_STRCMP((const char *) DUK_HSTRING_GET_DATA(h_dir), "use duk notail") == 0) {
71756 					DUK_DDD(DUK_DDDPRINT("use duk notail directive detected: notail flag %ld -> %ld",
71757 					                     (long) comp_ctx->curr_func.is_notail, (long) 1));
71758 					comp_ctx->curr_func.is_notail = 1;
71759 				} else {
71760 					DUK_DD(DUK_DDPRINT("unknown directive: '%!O', ignoring but not terminating "
71761 					                   "directive prologue", (duk_hobject *) h_dir));
71762 				}
71763 			}
71764 		} else {
71765 			DUK_DDD(DUK_DDDPRINT("non-directive expression statement or no longer in prologue; "
71766 			                     "prologue terminated if still active"));
71767                 }
71768 
71769 		stmt_flags |= DUK__HAS_VAL | DUK__HAS_TERM;
71770 	}
71771 	}  /* end switch (tok) */
71772 
71773 	/*
71774 	 *  Statement value handling.
71775 	 *
71776 	 *  Global code and eval code has an implicit return value
71777 	 *  which comes from the last statement with a value
71778 	 *  (technically a non-"empty" continuation, which is
71779 	 *  different from an empty statement).
71780 	 *
71781 	 *  Since we don't know whether a later statement will
71782 	 *  override the value of the current statement, we need
71783 	 *  to coerce the statement value to a register allocated
71784 	 *  for implicit return values.  In other cases we need
71785 	 *  to coerce the statement value to a plain value to get
71786 	 *  any side effects out (consider e.g. "foo.bar;").
71787 	 */
71788 
71789 	/* XXX: what about statements which leave a half-cooked value in 'res'
71790 	 * but have no stmt value?  Any such statements?
71791 	 */
71792 
71793 	if (stmt_flags & DUK__HAS_VAL) {
71794 		duk_regconst_t reg_stmt_value = comp_ctx->curr_func.reg_stmt_value;
71795 		if (reg_stmt_value >= 0) {
71796 			duk__ivalue_toforcedreg(comp_ctx, res, reg_stmt_value);
71797 		} else {
71798 			duk__ivalue_toplain_ignore(comp_ctx, res);
71799 		}
71800 	} else {
71801 		;
71802 	}
71803 
71804 	/*
71805 	 *  Statement terminator check, including automatic semicolon
71806 	 *  handling.  After this step, 'curr_tok' should be the first
71807 	 *  token after a possible statement terminator.
71808 	 */
71809 
71810 	if (stmt_flags & DUK__HAS_TERM) {
71811 		if (comp_ctx->curr_token.t == DUK_TOK_SEMICOLON) {
71812 			DUK_DDD(DUK_DDDPRINT("explicit semicolon terminates statement"));
71813 			duk__advance(comp_ctx);
71814 		} else {
71815 			if (comp_ctx->curr_token.allow_auto_semi) {
71816 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement"));
71817 			} else if (stmt_flags & DUK__ALLOW_AUTO_SEMI_ALWAYS) {
71818 				/* XXX: make this lenience dependent on flags or strictness? */
71819 				DUK_DDD(DUK_DDDPRINT("automatic semicolon terminates statement (allowed for compatibility "
71820 				                     "even though no lineterm present before next token)"));
71821 			} else {
71822 				DUK_ERROR_SYNTAX(thr, DUK_STR_UNTERMINATED_STMT);
71823 				DUK_WO_NORETURN(return;);
71824 			}
71825 		}
71826 	} else {
71827 		DUK_DDD(DUK_DDDPRINT("statement has no terminator"));
71828 	}
71829 
71830 	/*
71831 	 *  Directive prologue tracking.
71832 	 */
71833 
71834 	if (stmt_flags & DUK__STILL_PROLOGUE) {
71835 		DUK_DDD(DUK_DDDPRINT("setting in_directive_prologue"));
71836 		comp_ctx->curr_func.in_directive_prologue = 1;
71837 	}
71838 
71839 	/*
71840 	 *  Cleanups (all statement parsing flows through here).
71841 	 *
71842 	 *  Pop label site and reset labels.  Reset 'next temp' to value at
71843 	 *  entry to reuse temps.
71844 	 */
71845 
71846 	if (label_id >= 0) {
71847 		duk__emit_bc(comp_ctx,
71848 		             DUK_OP_ENDLABEL,
71849 		             (duk_regconst_t) label_id);
71850 	}
71851 
71852 	DUK__SETTEMP(comp_ctx, temp_at_entry);
71853 
71854 	duk__reset_labels_to_length(comp_ctx, labels_len_at_entry);
71855 
71856 	/* XXX: return indication of "terminalness" (e.g. a 'throw' is terminal) */
71857 
71858 	DUK__RECURSION_DECREASE(comp_ctx, thr);
71859 }
71860 
71861 /*
71862  *  Parse a statement list.
71863  *
71864  *  Handles automatic semicolon insertion and implicit return value.
71865  *
71866  *  Upon entry, 'curr_tok' should contain the first token of the first
71867  *  statement (parsed in the "allow regexp literal" mode).  Upon exit,
71868  *  'curr_tok' contains the token following the statement list terminator
71869  *  (EOF or closing brace).
71870  */
71871 
71872 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) {
71873 	duk_hthread *thr = comp_ctx->thr;
71874 	duk_ivalue res_alloc;
71875 	duk_ivalue *res = &res_alloc;
71876 
71877 	/* Setup state.  Initial ivalue is 'undefined'. */
71878 
71879 	duk_require_stack(thr, DUK__PARSE_STATEMENTS_SLOTS);
71880 
71881 	/* XXX: 'res' setup can be moved to function body level; in fact, two 'res'
71882 	 * intermediate values suffice for parsing of each function.  Nesting is needed
71883 	 * for nested functions (which may occur inside expressions).
71884 	 */
71885 
71886 	duk_memzero(&res_alloc, sizeof(res_alloc));
71887 	res->t = DUK_IVAL_PLAIN;
71888 	res->x1.t = DUK_ISPEC_VALUE;
71889 	res->x1.valstack_idx = duk_get_top(thr);
71890 	res->x2.valstack_idx = res->x1.valstack_idx + 1;
71891 	duk_push_undefined(thr);
71892 	duk_push_undefined(thr);
71893 
71894 	/* Parse statements until a closing token (EOF or '}') is found. */
71895 
71896 	for (;;) {
71897 		/* Check whether statement list ends. */
71898 
71899 		if (expect_eof) {
71900 			if (comp_ctx->curr_token.t == DUK_TOK_EOF) {
71901 				break;
71902 			}
71903 		} else {
71904 			if (comp_ctx->curr_token.t == DUK_TOK_RCURLY) {
71905 				break;
71906 			}
71907 		}
71908 
71909 		/* Check statement type based on the first token type.
71910 		 *
71911 		 * Note: expression parsing helpers expect 'curr_tok' to
71912 		 * contain the first token of the expression upon entry.
71913 		 */
71914 
71915 		DUK_DDD(DUK_DDDPRINT("TOKEN %ld (non-whitespace, non-comment)", (long) comp_ctx->curr_token.t));
71916 
71917 		duk__parse_stmt(comp_ctx, res, allow_source_elem);
71918 	}
71919 
71920 	/* RegExp is allowed / not allowed depending on context.  For function
71921 	 * declarations RegExp is allowed because it follows a function
71922 	 * declaration statement and may appear as part of the next statement.
71923 	 * For function expressions RegExp is not allowed, and it's possible
71924 	 * to do something like '(function () {} / 123)'.
71925 	 */
71926 	if (regexp_after) {
71927 		comp_ctx->curr_func.allow_regexp_in_adv = 1;
71928 	}
71929 	duk__advance(comp_ctx);
71930 
71931 	/* Tear down state. */
71932 
71933 	duk_pop_2(thr);
71934 }
71935 
71936 /*
71937  *  Declaration binding instantiation conceptually happens when calling a
71938  *  function; for us it essentially means that function prologue.  The
71939  *  conceptual process is described in E5 Section 10.5.
71940  *
71941  *  We need to keep track of all encountered identifiers to (1) create an
71942  *  identifier-to-register map ("varmap"); and (2) detect duplicate
71943  *  declarations.  Identifiers which are not bound to registers still need
71944  *  to be tracked for detecting duplicates.  Currently such identifiers
71945  *  are put into the varmap with a 'null' value, which is later cleaned up.
71946  *
71947  *  To support functions with a large number of variable and function
71948  *  declarations, registers are not allocated beyond a certain limit;
71949  *  after that limit, variables and functions need slow path access.
71950  *  Arguments are currently always register bound, which imposes a hard
71951  *  (and relatively small) argument count limit.
71952  *
71953  *  Some bindings in E5 are not configurable (= deletable) and almost all
71954  *  are mutable (writable).  Exceptions are:
71955  *
71956  *    - The 'arguments' binding, established only if no shadowing argument
71957  *      or function declaration exists.  We handle 'arguments' creation
71958  *      and binding through an explicit slow path environment record.
71959  *
71960  *    - The "name" binding for a named function expression.  This is also
71961  *      handled through an explicit slow path environment record.
71962  */
71963 
71964 /* XXX: add support for variables to not be register bound always, to
71965  * handle cases with a very large number of variables?
71966  */
71967 
71968 DUK_LOCAL void duk__init_varmap_and_prologue_for_pass2(duk_compiler_ctx *comp_ctx, duk_regconst_t *out_stmt_value_reg) {
71969 	duk_hthread *thr = comp_ctx->thr;
71970 	duk_hstring *h_name;
71971 	duk_bool_t configurable_bindings;
71972 	duk_uarridx_t num_args;
71973 	duk_uarridx_t num_decls;
71974 	duk_regconst_t rc_name;
71975 	duk_small_uint_t declvar_flags;
71976 	duk_uarridx_t i;
71977 #if defined(DUK_USE_ASSERTIONS)
71978 	duk_idx_t entry_top;
71979 #endif
71980 
71981 #if defined(DUK_USE_ASSERTIONS)
71982 	entry_top = duk_get_top(thr);
71983 #endif
71984 
71985 	/*
71986 	 *  Preliminaries
71987 	 */
71988 
71989 	configurable_bindings = comp_ctx->curr_func.is_eval;
71990 	DUK_DDD(DUK_DDDPRINT("configurable_bindings=%ld", (long) configurable_bindings));
71991 
71992 	/* varmap is already in comp_ctx->curr_func.varmap_idx */
71993 
71994 	/*
71995 	 *  Function formal arguments, always bound to registers
71996 	 *  (there's no support for shuffling them now).
71997 	 */
71998 
71999 	num_args = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
72000 	DUK_DDD(DUK_DDDPRINT("num_args=%ld", (long) num_args));
72001 	/* XXX: check num_args */
72002 
72003 	for (i = 0; i < num_args; i++) {
72004 		duk_get_prop_index(thr, comp_ctx->curr_func.argnames_idx, i);
72005 		h_name = duk_known_hstring(thr, -1);
72006 
72007 		if (comp_ctx->curr_func.is_strict) {
72008 			if (duk__hstring_is_eval_or_arguments(comp_ctx, h_name)) {
72009 				DUK_DDD(DUK_DDDPRINT("arg named 'eval' or 'arguments' in strict mode -> SyntaxError"));
72010 				goto error_argname;
72011 			}
72012 			duk_dup_top(thr);
72013 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72014 				DUK_DDD(DUK_DDDPRINT("duplicate arg name in strict mode -> SyntaxError"));
72015 				goto error_argname;
72016 			}
72017 
72018 			/* Ensure argument name is not a reserved word in current
72019 			 * (final) strictness.  Formal argument parsing may not
72020 			 * catch reserved names if strictness changes during
72021 			 * parsing.
72022 			 *
72023 			 * We only need to do this in strict mode because non-strict
72024 			 * keyword are always detected in formal argument parsing.
72025 			 */
72026 
72027 			if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(h_name)) {
72028 				goto error_argname;
72029 			}
72030 		}
72031 
72032 		/* overwrite any previous binding of the same name; the effect is
72033 		 * that last argument of a certain name wins.
72034 		 */
72035 
72036 		/* only functions can have arguments */
72037 		DUK_ASSERT(comp_ctx->curr_func.is_function);
72038 		duk_push_uarridx(thr, i);  /* -> [ ... name index ] */
72039 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx); /* -> [ ... ] */
72040 
72041 		/* no code needs to be emitted, the regs already have values */
72042 	}
72043 
72044 	/* use temp_next for tracking register allocations */
72045 	DUK__SETTEMP_CHECKMAX(comp_ctx, (duk_regconst_t) num_args);
72046 
72047 	/*
72048 	 *  After arguments, allocate special registers (like shuffling temps)
72049 	 */
72050 
72051 	if (out_stmt_value_reg) {
72052 		*out_stmt_value_reg = DUK__ALLOCTEMP(comp_ctx);
72053 	}
72054 	if (comp_ctx->curr_func.needs_shuffle) {
72055 		duk_regconst_t shuffle_base = DUK__ALLOCTEMPS(comp_ctx, 3);
72056 		comp_ctx->curr_func.shuffle1 = shuffle_base;
72057 		comp_ctx->curr_func.shuffle2 = shuffle_base + 1;
72058 		comp_ctx->curr_func.shuffle3 = shuffle_base + 2;
72059 		DUK_D(DUK_DPRINT("shuffle registers needed by function, allocated: %ld %ld %ld",
72060 		                 (long) comp_ctx->curr_func.shuffle1,
72061 		                 (long) comp_ctx->curr_func.shuffle2,
72062 		                 (long) comp_ctx->curr_func.shuffle3));
72063 	}
72064 	if (comp_ctx->curr_func.temp_next > 0x100) {
72065 		DUK_D(DUK_DPRINT("not enough 8-bit regs: temp_next=%ld", (long) comp_ctx->curr_func.temp_next));
72066 		goto error_outofregs;
72067 	}
72068 
72069 	/*
72070 	 *  Function declarations
72071 	 */
72072 
72073 	num_decls = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.decls_idx);
72074 	DUK_DDD(DUK_DDDPRINT("num_decls=%ld -> %!T",
72075 	                     (long) num_decls,
72076 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.decls_idx)));
72077 	for (i = 0; i < num_decls; i += 2) {
72078 		duk_int_t decl_type;
72079 		duk_int_t fnum;
72080 
72081 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72082 		decl_type = duk_to_int(thr, -1);
72083 		fnum = decl_type >> 8;  /* XXX: macros */
72084 		decl_type = decl_type & 0xff;
72085 		duk_pop(thr);
72086 
72087 		if (decl_type != DUK_DECL_TYPE_FUNC) {
72088 			continue;
72089 		}
72090 
72091 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72092 
72093 		/* XXX: spilling */
72094 		if (comp_ctx->curr_func.is_function) {
72095 			duk_regconst_t reg_bind;
72096 			duk_dup_top(thr);
72097 			if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72098 				/* shadowed; update value */
72099 				duk_dup_top(thr);
72100 				duk_get_prop(thr, comp_ctx->curr_func.varmap_idx);
72101 				reg_bind = duk_to_int(thr, -1);  /* [ ... name reg_bind ] */
72102 				duk__emit_a_bc(comp_ctx,
72103 				               DUK_OP_CLOSURE,
72104 				               reg_bind,
72105 				               (duk_regconst_t) fnum);
72106 			} else {
72107 				/* function: always register bound */
72108 				reg_bind = DUK__ALLOCTEMP(comp_ctx);
72109 				duk__emit_a_bc(comp_ctx,
72110 				               DUK_OP_CLOSURE,
72111 				               reg_bind,
72112 				               (duk_regconst_t) fnum);
72113 				duk_push_int(thr, (duk_int_t) reg_bind);
72114 			}
72115 		} else {
72116 			/* Function declaration for global/eval code is emitted even
72117 			 * for duplicates, because of E5 Section 10.5, step 5.e of
72118 			 * E5.1 (special behavior for variable bound to global object).
72119 			 *
72120 			 * DECLVAR will not re-declare a variable as such, but will
72121 			 * update the binding value.
72122 			 */
72123 
72124 			duk_regconst_t reg_temp = DUK__ALLOCTEMP(comp_ctx);
72125 			duk_dup_top(thr);
72126 			rc_name = duk__getconst(comp_ctx);
72127 			duk_push_null(thr);
72128 
72129 			duk__emit_a_bc(comp_ctx,
72130 			               DUK_OP_CLOSURE,
72131 			               reg_temp,
72132 			               (duk_regconst_t) fnum);
72133 
72134 			declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72135 			                DUK_PROPDESC_FLAG_ENUMERABLE |
72136 			                DUK_BC_DECLVAR_FLAG_FUNC_DECL;
72137 
72138 			if (configurable_bindings) {
72139 				declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72140 			}
72141 
72142 			duk__emit_a_b_c(comp_ctx,
72143 			                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72144 			                (duk_regconst_t) declvar_flags /*flags*/,
72145 			                rc_name /*name*/,
72146 			                reg_temp /*value*/);
72147 
72148 			DUK__SETTEMP(comp_ctx, reg_temp);  /* forget temp */
72149 		}
72150 
72151 		DUK_DDD(DUK_DDDPRINT("function declaration to varmap: %!T -> %!T",
72152 		                     (duk_tval *) duk_get_tval(thr, -2),
72153 		                     (duk_tval *) duk_get_tval(thr, -1)));
72154 
72155 #if defined(DUK_USE_FASTINT)
72156 		DUK_ASSERT(DUK_TVAL_IS_NULL(duk_get_tval(thr, -1)) || DUK_TVAL_IS_FASTINT(duk_get_tval(thr, -1)));
72157 #endif
72158 		duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72159 	}
72160 
72161 	/*
72162 	 *  'arguments' binding is special; if a shadowing argument or
72163 	 *  function declaration exists, an arguments object will
72164 	 *  definitely not be needed, regardless of whether the identifier
72165 	 *  'arguments' is referenced inside the function body.
72166 	 */
72167 
72168 	if (duk_has_prop_stridx(thr, comp_ctx->curr_func.varmap_idx, DUK_STRIDX_LC_ARGUMENTS)) {
72169 		DUK_DDD(DUK_DDDPRINT("'arguments' is shadowed by argument or function declaration "
72170 		                     "-> arguments object creation can be skipped"));
72171 		comp_ctx->curr_func.is_arguments_shadowed = 1;
72172 	}
72173 
72174 	/*
72175 	 *  Variable declarations.
72176 	 *
72177 	 *  Unlike function declarations, variable declaration values don't get
72178 	 *  assigned on entry.  If a binding of the same name already exists, just
72179 	 *  ignore it silently.
72180 	 */
72181 
72182 	for (i = 0; i < num_decls; i += 2) {
72183 		duk_int_t decl_type;
72184 
72185 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i + 1);  /* decl type */
72186 		decl_type = duk_to_int(thr, -1);
72187 		decl_type = decl_type & 0xff;
72188 		duk_pop(thr);
72189 
72190 		if (decl_type != DUK_DECL_TYPE_VAR) {
72191 			continue;
72192 		}
72193 
72194 		duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72195 
72196 		if (duk_has_prop(thr, comp_ctx->curr_func.varmap_idx)) {
72197 			/* shadowed, ignore */
72198 		} else {
72199 			duk_get_prop_index(thr, comp_ctx->curr_func.decls_idx, i);  /* decl name */
72200 			h_name = duk_known_hstring(thr, -1);
72201 
72202 			if (h_name == DUK_HTHREAD_STRING_LC_ARGUMENTS(thr) &&
72203 			    !comp_ctx->curr_func.is_arguments_shadowed) {
72204 				/* E5 Section steps 7-8 */
72205 				DUK_DDD(DUK_DDDPRINT("'arguments' not shadowed by a function declaration, "
72206 				                     "but appears as a variable declaration -> treat as "
72207 				                     "a no-op for variable declaration purposes"));
72208 				duk_pop(thr);
72209 				continue;
72210 			}
72211 
72212 			/* XXX: spilling */
72213 			if (comp_ctx->curr_func.is_function) {
72214 				duk_regconst_t reg_bind = DUK__ALLOCTEMP(comp_ctx);
72215 				/* no need to init reg, it will be undefined on entry */
72216 				duk_push_int(thr, (duk_int_t) reg_bind);
72217 			} else {
72218 				duk_dup_top(thr);
72219 				rc_name = duk__getconst(comp_ctx);
72220 				duk_push_null(thr);
72221 
72222 				declvar_flags = DUK_PROPDESC_FLAG_WRITABLE |
72223 			                        DUK_PROPDESC_FLAG_ENUMERABLE;
72224 				if (configurable_bindings) {
72225 					declvar_flags |= DUK_PROPDESC_FLAG_CONFIGURABLE;
72226 				}
72227 
72228 				duk__emit_a_b_c(comp_ctx,
72229 				                DUK_OP_DECLVAR | DUK__EMIT_FLAG_NO_SHUFFLE_A | DUK__EMIT_FLAG_BC_REGCONST,
72230 				                (duk_regconst_t) declvar_flags /*flags*/,
72231 				                rc_name /*name*/,
72232 				                0 /*value*/);
72233 			}
72234 
72235 			duk_put_prop(thr, comp_ctx->curr_func.varmap_idx);  /* [ ... name reg/null ] -> [ ... ] */
72236 		}
72237 	}
72238 
72239 	/*
72240 	 *  Wrap up
72241 	 */
72242 
72243 	DUK_DDD(DUK_DDDPRINT("varmap: %!T, is_arguments_shadowed=%ld",
72244 	                     (duk_tval *) duk_get_tval(thr, comp_ctx->curr_func.varmap_idx),
72245 	                     (long) comp_ctx->curr_func.is_arguments_shadowed));
72246 
72247 	DUK_ASSERT_TOP(thr, entry_top);
72248 	return;
72249 
72250  error_outofregs:
72251 	DUK_ERROR_RANGE(thr, DUK_STR_REG_LIMIT);
72252 	DUK_WO_NORETURN(return;);
72253 
72254  error_argname:
72255 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_ARG_NAME);
72256 	DUK_WO_NORETURN(return;);
72257 }
72258 
72259 /*
72260  *  Parse a function-body-like expression (FunctionBody or Program
72261  *  in E5 grammar) using a two-pass parse.  The productions appear
72262  *  in the following contexts:
72263  *
72264  *    - function expression
72265  *    - function statement
72266  *    - function declaration
72267  *    - getter in object literal
72268  *    - setter in object literal
72269  *    - global code
72270  *    - eval code
72271  *    - Function constructor body
72272  *
72273  *  This function only parses the statement list of the body; the argument
72274  *  list and possible function name must be initialized by the caller.
72275  *  For instance, for Function constructor, the argument names are originally
72276  *  on the value stack.  The parsing of statements ends either at an EOF or
72277  *  a closing brace; this is controlled by an input flag.
72278  *
72279  *  Note that there are many differences affecting parsing and even code
72280  *  generation:
72281  *
72282  *    - Global and eval code have an implicit return value generated
72283  *      by the last statement; function code does not
72284  *
72285  *    - Global code, eval code, and Function constructor body end in
72286  *      an EOF, other bodies in a closing brace ('}')
72287  *
72288  *  Upon entry, 'curr_tok' is ignored and the function will pull in the
72289  *  first token on its own.  Upon exit, 'curr_tok' is the terminating
72290  *  token (EOF or closing brace).
72291  */
72292 
72293 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) {
72294 	duk_compiler_func *func;
72295 	duk_hthread *thr;
72296 	duk_regconst_t reg_stmt_value = -1;
72297 	duk_lexer_point lex_pt;
72298 	duk_regconst_t temp_first;
72299 	duk_small_int_t compile_round = 1;
72300 
72301 	DUK_ASSERT(comp_ctx != NULL);
72302 
72303 	thr = comp_ctx->thr;
72304 	DUK_ASSERT(thr != NULL);
72305 
72306 	func = &comp_ctx->curr_func;
72307 	DUK_ASSERT(func != NULL);
72308 
72309 	DUK__RECURSION_INCREASE(comp_ctx, thr);
72310 
72311 	duk_require_stack(thr, DUK__FUNCTION_BODY_REQUIRE_SLOTS);
72312 
72313 	/*
72314 	 *  Store lexer position for a later rewind
72315 	 */
72316 
72317 	DUK_LEXER_GETPOINT(&comp_ctx->lex, &lex_pt);
72318 
72319 	/*
72320 	 *  Program code (global and eval code) has an implicit return value
72321 	 *  from the last statement value (e.g. eval("1; 2+3;") returns 3).
72322 	 *  This is not the case with functions.  If implicit statement return
72323 	 *  value is requested, all statements are coerced to a register
72324 	 *  allocated here, and used in the implicit return statement below.
72325 	 */
72326 
72327 	/* XXX: this is pointless here because pass 1 is throw-away */
72328 	if (implicit_return_value) {
72329 		reg_stmt_value = DUK__ALLOCTEMP(comp_ctx);
72330 
72331 		/* If an implicit return value is needed by caller, it must be
72332 		 * initialized to 'undefined' because we don't know whether any
72333 		 * non-empty (where "empty" is a continuation type, and different
72334 		 * from an empty statement) statements will be executed.
72335 		 *
72336 		 * However, since 1st pass is a throwaway one, no need to emit
72337 		 * it here.
72338 		 */
72339 #if 0
72340 		duk__emit_bc(comp_ctx,
72341 		             DUK_OP_LDUNDEF,
72342 		             0);
72343 #endif
72344 	}
72345 
72346 	/*
72347 	 *  First pass.
72348 	 *
72349 	 *  Gather variable/function declarations needed for second pass.
72350 	 *  Code generated is dummy and discarded.
72351 	 */
72352 
72353 	func->in_directive_prologue = 1;
72354 	func->in_scanning = 1;
72355 	func->may_direct_eval = 0;
72356 	func->id_access_arguments = 0;
72357 	func->id_access_slow = 0;
72358 	func->id_access_slow_own = 0;
72359 	func->reg_stmt_value = reg_stmt_value;
72360 #if defined(DUK_USE_DEBUGGER_SUPPORT)
72361 	func->min_line = DUK_INT_MAX;
72362 	func->max_line = 0;
72363 #endif
72364 
72365 	/* duk__parse_stmts() expects curr_tok to be set; parse in "allow
72366 	 * regexp literal" mode with current strictness.
72367 	 */
72368 	if (expect_token >= 0) {
72369 		/* Eating a left curly; regexp mode is allowed by left curly
72370 		 * based on duk__token_lbp[] automatically.
72371 		 */
72372 		DUK_ASSERT(expect_token == DUK_TOK_LCURLY);
72373 		duk__update_lineinfo_currtoken(comp_ctx);
72374 		duk__advance_expect(comp_ctx, expect_token);
72375 	} else {
72376 		/* Need to set curr_token.t because lexing regexp mode depends on current
72377 		 * token type.  Zero value causes "allow regexp" mode.
72378 		 */
72379 		comp_ctx->curr_token.t = 0;
72380 		duk__advance(comp_ctx);
72381 	}
72382 
72383 	DUK_DDD(DUK_DDDPRINT("begin 1st pass"));
72384 	duk__parse_stmts(comp_ctx,
72385 	                 1,             /* allow source elements */
72386 	                 expect_eof,    /* expect EOF instead of } */
72387 	                 regexp_after); /* regexp after */
72388 	DUK_DDD(DUK_DDDPRINT("end 1st pass"));
72389 
72390 	/*
72391 	 *  Second (and possibly third) pass.
72392 	 *
72393 	 *  Generate actual code.  In most cases the need for shuffle
72394 	 *  registers is detected during pass 1, but in some corner cases
72395 	 *  we'll only detect it during pass 2 and a third pass is then
72396 	 *  needed (see GH-115).
72397 	 */
72398 
72399 	for (;;) {
72400 		duk_bool_t needs_shuffle_before = comp_ctx->curr_func.needs_shuffle;
72401 		compile_round++;
72402 
72403 		/*
72404 		 *  Rewind lexer.
72405 		 *
72406 		 *  duk__parse_stmts() expects curr_tok to be set; parse in "allow regexp
72407 		 *  literal" mode with current strictness.
72408 		 *
72409 		 *  curr_token line number info should be initialized for pass 2 before
72410 		 *  generating prologue, to ensure prologue bytecode gets nice line numbers.
72411 		 */
72412 
72413 		DUK_DDD(DUK_DDDPRINT("rewind lexer"));
72414 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
72415 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
72416 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72417 		duk__advance(comp_ctx);
72418 
72419 		/*
72420 		 *  Reset function state and perform register allocation, which creates
72421 		 *  'varmap' for second pass.  Function prologue for variable declarations,
72422 		 *  binding value initializations etc is emitted as a by-product.
72423 		 *
72424 		 *  Strict mode restrictions for duplicate and invalid argument
72425 		 *  names are checked here now that we know whether the function
72426 		 *  is actually strict.  See: test-dev-strict-mode-boundary.js.
72427 		 *
72428 		 *  Inner functions are compiled during pass 1 and are not reset.
72429 		 */
72430 
72431 		duk__reset_func_for_pass2(comp_ctx);
72432 		func->in_directive_prologue = 1;
72433 		func->in_scanning = 0;
72434 
72435 		/* must be able to emit code, alloc consts, etc. */
72436 
72437 		duk__init_varmap_and_prologue_for_pass2(comp_ctx,
72438 		                                        (implicit_return_value ? &reg_stmt_value : NULL));
72439 		func->reg_stmt_value = reg_stmt_value;
72440 
72441 		temp_first = DUK__GETTEMP(comp_ctx);
72442 
72443 		func->temp_first = temp_first;
72444 		func->temp_next = temp_first;
72445 		func->stmt_next = 0;
72446 		func->label_next = 0;
72447 
72448 		/* XXX: init or assert catch depth etc -- all values */
72449 		func->id_access_arguments = 0;
72450 		func->id_access_slow = 0;
72451 		func->id_access_slow_own = 0;
72452 
72453 		/*
72454 		 *  Check function name validity now that we know strictness.
72455 		 *  This only applies to function declarations and expressions,
72456 		 *  not setter/getter name.
72457 		 *
72458 		 *  See: test-dev-strict-mode-boundary.js
72459 		 */
72460 
72461 		if (func->is_function && !func->is_setget && func->h_name != NULL) {
72462 			if (func->is_strict) {
72463 				if (duk__hstring_is_eval_or_arguments(comp_ctx, func->h_name)) {
72464 					DUK_DDD(DUK_DDDPRINT("func name is 'eval' or 'arguments' in strict mode"));
72465 					goto error_funcname;
72466 				}
72467 				if (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
72468 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in strict mode"));
72469 					goto error_funcname;
72470 				}
72471 			} else {
72472 				if (DUK_HSTRING_HAS_RESERVED_WORD(func->h_name) &&
72473 				    !DUK_HSTRING_HAS_STRICT_RESERVED_WORD(func->h_name)) {
72474 					DUK_DDD(DUK_DDDPRINT("func name is a reserved word in non-strict mode"));
72475 					goto error_funcname;
72476 				}
72477 			}
72478 		}
72479 
72480 		/*
72481 		 *  Second pass parsing.
72482 		 */
72483 
72484 		if (implicit_return_value) {
72485 			/* Default implicit return value. */
72486 			duk__emit_bc(comp_ctx,
72487 			             DUK_OP_LDUNDEF,
72488 			             0);
72489 		}
72490 
72491 		DUK_DDD(DUK_DDDPRINT("begin 2nd pass"));
72492 		duk__parse_stmts(comp_ctx,
72493 		                 1,             /* allow source elements */
72494 		                 expect_eof,    /* expect EOF instead of } */
72495 		                 regexp_after); /* regexp after */
72496 		DUK_DDD(DUK_DDDPRINT("end 2nd pass"));
72497 
72498 		duk__update_lineinfo_currtoken(comp_ctx);
72499 
72500 		if (needs_shuffle_before == comp_ctx->curr_func.needs_shuffle) {
72501 			/* Shuffle decision not changed. */
72502 			break;
72503 		}
72504 		if (compile_round >= 3) {
72505 			/* Should never happen but avoid infinite loop just in case. */
72506 			DUK_D(DUK_DPRINT("more than 3 compile passes needed, should never happen"));
72507 			DUK_ERROR_INTERNAL(thr);
72508 			DUK_WO_NORETURN(return;);
72509 		}
72510 		DUK_D(DUK_DPRINT("need additional round to compile function, round now %d", (int) compile_round));
72511 	}
72512 
72513 	/*
72514 	 *  Emit a final RETURN.
72515 	 *
72516 	 *  It would be nice to avoid emitting an unnecessary "return" opcode
72517 	 *  if the current PC is not reachable.  However, this cannot be reliably
72518 	 *  detected; even if the previous instruction is an unconditional jump,
72519 	 *  there may be a previous jump which jumps to current PC (which is the
72520 	 *  case for iteration and conditional statements, for instance).
72521 	 */
72522 
72523 	/* XXX: request a "last statement is terminal" from duk__parse_stmt() and duk__parse_stmts();
72524 	 * we could avoid the last RETURN if we could ensure there is no way to get here
72525 	 * (directly or via a jump)
72526 	 */
72527 
72528 	DUK_ASSERT(comp_ctx->curr_func.catch_depth == 0);
72529 	if (reg_stmt_value >= 0) {
72530 		DUK_ASSERT(DUK__ISREG(reg_stmt_value));
72531 		duk__emit_bc(comp_ctx, DUK_OP_RETREG, reg_stmt_value /*reg*/);
72532 	} else {
72533 		duk__emit_op_only(comp_ctx, DUK_OP_RETUNDEF);
72534 	}
72535 
72536 	/*
72537 	 *  Peephole optimize JUMP chains.
72538 	 */
72539 
72540 	duk__peephole_optimize_bytecode(comp_ctx);
72541 
72542 	/*
72543 	 *  comp_ctx->curr_func is now ready to be converted into an actual
72544 	 *  function template.
72545 	 */
72546 
72547 	DUK__RECURSION_DECREASE(comp_ctx, thr);
72548 	return;
72549 
72550  error_funcname:
72551 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_FUNC_NAME);
72552 	DUK_WO_NORETURN(return;);
72553 }
72554 
72555 /*
72556  *  Parse a function-like expression:
72557  *
72558  *    - function expression
72559  *    - function declaration
72560  *    - function statement (non-standard)
72561  *    - setter/getter
72562  *
72563  *  Adds the function to comp_ctx->curr_func function table and returns the
72564  *  function number.
72565  *
72566  *  On entry, curr_token points to:
72567  *
72568  *    - the token after 'function' for function expression/declaration/statement
72569  *    - the token after 'set' or 'get' for setter/getter
72570  */
72571 
72572 /* Parse formals. */
72573 DUK_LOCAL void duk__parse_func_formals(duk_compiler_ctx *comp_ctx) {
72574 	duk_hthread *thr = comp_ctx->thr;
72575 	duk_bool_t first = 1;
72576 	duk_uarridx_t n;
72577 
72578 	for (;;) {
72579 		if (comp_ctx->curr_token.t == DUK_TOK_RPAREN) {
72580 			break;
72581 		}
72582 
72583 		if (first) {
72584 			/* no comma */
72585 			first = 0;
72586 		} else {
72587 			duk__advance_expect(comp_ctx, DUK_TOK_COMMA);
72588 		}
72589 
72590 		/* Note: when parsing a formal list in non-strict context, e.g.
72591 		 * "implements" is parsed as an identifier.  When the function is
72592 		 * later detected to be strict, the argument list must be rechecked
72593 		 * against a larger set of reserved words (that of strict mode).
72594 		 * This is handled by duk__parse_func_body().  Here we recognize
72595 		 * whatever tokens are considered reserved in current strictness
72596 		 * (which is not always enough).
72597 		 */
72598 
72599 		if (comp_ctx->curr_token.t != DUK_TOK_IDENTIFIER) {
72600 			DUK_ERROR_SYNTAX(thr, DUK_STR_EXPECTED_IDENTIFIER);
72601 			DUK_WO_NORETURN(return;);
72602 		}
72603 		DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_IDENTIFIER);
72604 		DUK_ASSERT(comp_ctx->curr_token.str1 != NULL);
72605 		DUK_DDD(DUK_DDDPRINT("formal argument: %!O",
72606 		                     (duk_heaphdr *) comp_ctx->curr_token.str1));
72607 
72608 		/* XXX: append primitive */
72609 		duk_push_hstring(thr, comp_ctx->curr_token.str1);
72610 		n = (duk_uarridx_t) duk_get_length(thr, comp_ctx->curr_func.argnames_idx);
72611 		duk_put_prop_index(thr, comp_ctx->curr_func.argnames_idx, n);
72612 
72613 		duk__advance(comp_ctx);  /* eat identifier */
72614 	}
72615 }
72616 
72617 /* Parse a function-like expression, assuming that 'comp_ctx->curr_func' is
72618  * correctly set up.  Assumes that curr_token is just after 'function' (or
72619  * 'set'/'get' etc).
72620  */
72621 DUK_LOCAL void duk__parse_func_like_raw(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
72622 	duk_hthread *thr = comp_ctx->thr;
72623 	duk_token *tok;
72624 	duk_bool_t no_advance;
72625 
72626 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
72627 	DUK_ASSERT(comp_ctx->curr_func.is_function == 1);
72628 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
72629 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
72630 	DUK_ASSERT(comp_ctx->curr_func.is_setget == ((flags & DUK__FUNC_FLAG_GETSET) != 0));
72631 
72632 	duk__update_lineinfo_currtoken(comp_ctx);
72633 
72634 	/*
72635 	 *  Function name (if any)
72636 	 *
72637 	 *  We don't check for prohibited names here, because we don't
72638 	 *  yet know whether the function will be strict.  Function body
72639 	 *  parsing handles this retroactively.
72640 	 *
72641 	 *  For function expressions and declarations function name must
72642 	 *  be an Identifer (excludes reserved words).  For setter/getter
72643 	 *  it is a PropertyName which allows reserved words and also
72644 	 *  strings and numbers (e.g. "{ get 1() { ... } }").
72645 	 *
72646 	 *  Function parsing may start either from prev_token or curr_token
72647 	 *  (object literal method definition uses prev_token for example).
72648 	 *  This is dealt with for the initial token.
72649 	 */
72650 
72651 	no_advance = (flags & DUK__FUNC_FLAG_USE_PREVTOKEN);
72652 	if (no_advance) {
72653 		tok = &comp_ctx->prev_token;
72654 	} else {
72655 		tok = &comp_ctx->curr_token;
72656 	}
72657 
72658 	if (flags & DUK__FUNC_FLAG_GETSET) {
72659 		/* PropertyName -> IdentifierName | StringLiteral | NumericLiteral */
72660 		if (tok->t_nores == DUK_TOK_IDENTIFIER || tok->t == DUK_TOK_STRING) {
72661 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
72662 		} else if (tok->t == DUK_TOK_NUMBER) {
72663 			duk_push_number(thr, tok->num);
72664 			duk_to_string(thr, -1);
72665 		} else {
72666 			DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_GETSET_NAME);
72667 			DUK_WO_NORETURN(return;);
72668 		}
72669 		comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
72670 	} else {
72671 		/* Function name is an Identifier (not IdentifierName), but we get
72672 		 * the raw name (not recognizing keywords) here and perform the name
72673 		 * checks only after pass 1.
72674 		 */
72675 		if (tok->t_nores == DUK_TOK_IDENTIFIER) {
72676 			duk_push_hstring(thr, tok->str1);       /* keep in valstack */
72677 			comp_ctx->curr_func.h_name = duk_known_hstring(thr, -1);  /* borrowed reference */
72678 		} else {
72679 			/* valstack will be unbalanced, which is OK */
72680 			DUK_ASSERT((flags & DUK__FUNC_FLAG_GETSET) == 0);
72681 			DUK_ASSERT(comp_ctx->curr_func.h_name == NULL);
72682 			no_advance = 1;
72683 			if (flags & DUK__FUNC_FLAG_DECL) {
72684 				DUK_ERROR_SYNTAX(thr, DUK_STR_FUNC_NAME_REQUIRED);
72685 				DUK_WO_NORETURN(return;);
72686 			}
72687 		}
72688 	}
72689 
72690 	DUK_DD(DUK_DDPRINT("function name: %!O",
72691 	                   (duk_heaphdr *) comp_ctx->curr_func.h_name));
72692 
72693 	if (!no_advance) {
72694 		duk__advance(comp_ctx);
72695 	}
72696 
72697 	/*
72698 	 *  Formal argument list
72699 	 *
72700 	 *  We don't check for prohibited names or for duplicate argument
72701 	 *  names here, becase we don't yet know whether the function will
72702 	 *  be strict.  Function body parsing handles this retroactively.
72703 	 */
72704 
72705 	duk__advance_expect(comp_ctx, DUK_TOK_LPAREN);
72706 
72707 	duk__parse_func_formals(comp_ctx);
72708 
72709 	DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RPAREN);
72710 	duk__advance(comp_ctx);
72711 
72712 	/*
72713 	 *  Parse function body
72714 	 */
72715 
72716 	duk__parse_func_body(comp_ctx,
72717 	                     0,   /* expect_eof */
72718 	                     0,   /* implicit_return_value */
72719 	                     flags & DUK__FUNC_FLAG_DECL, /* regexp_after */
72720 	                     DUK_TOK_LCURLY);  /* expect_token */
72721 
72722 	/*
72723 	 *  Convert duk_compiler_func to a function template and add it
72724 	 *  to the parent function table.
72725 	 */
72726 
72727 	duk__convert_to_func_template(comp_ctx);  /* -> [ ... func ] */
72728 }
72729 
72730 /* Parse an inner function, adding the function template to the current function's
72731  * function table.  Return a function number to be used by the outer function.
72732  *
72733  * Avoiding O(depth^2) inner function parsing is handled here.  On the first pass,
72734  * compile and register the function normally into the 'funcs' array, also recording
72735  * a lexer point (offset/line) to the closing brace of the function.  On the second
72736  * pass, skip the function and return the same 'fnum' as on the first pass by using
72737  * a running counter.
72738  *
72739  * An unfortunate side effect of this is that when parsing the inner function, almost
72740  * nothing is known of the outer function, i.e. the inner function's scope.  We don't
72741  * need that information at the moment, but it would allow some optimizations if it
72742  * were used.
72743  */
72744 DUK_LOCAL duk_int_t duk__parse_func_like_fnum(duk_compiler_ctx *comp_ctx, duk_small_uint_t flags) {
72745 	duk_hthread *thr = comp_ctx->thr;
72746 	duk_compiler_func old_func;
72747 	duk_idx_t entry_top;
72748 	duk_int_t fnum;
72749 
72750 	/*
72751 	 *  On second pass, skip the function.
72752 	 */
72753 
72754 	if (!comp_ctx->curr_func.in_scanning) {
72755 		duk_lexer_point lex_pt;
72756 
72757 		fnum = comp_ctx->curr_func.fnum_next++;
72758 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
72759 		lex_pt.offset = (duk_size_t) duk_to_uint(thr, -1);
72760 		duk_pop(thr);
72761 		duk_get_prop_index(thr, comp_ctx->curr_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
72762 		lex_pt.line = duk_to_int(thr, -1);
72763 		duk_pop(thr);
72764 
72765 		DUK_DDD(DUK_DDDPRINT("second pass of an inner func, skip the function, reparse closing brace; lex offset=%ld, line=%ld",
72766 		                     (long) lex_pt.offset, (long) lex_pt.line));
72767 
72768 		DUK_LEXER_SETPOINT(&comp_ctx->lex, &lex_pt);
72769 		comp_ctx->curr_token.t = 0;  /* this is needed for regexp mode */
72770 		comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72771 		duk__advance(comp_ctx);
72772 
72773 		/* RegExp is not allowed after a function expression, e.g. in
72774 		 * (function () {} / 123).  A RegExp *is* allowed after a
72775 		 * function declaration!
72776 		 */
72777 		if (flags & DUK__FUNC_FLAG_DECL) {
72778 			comp_ctx->curr_func.allow_regexp_in_adv = 1;
72779 		}
72780 		duk__advance_expect(comp_ctx, DUK_TOK_RCURLY);
72781 
72782 		return fnum;
72783 	}
72784 
72785 	/*
72786 	 *  On first pass, perform actual parsing.  Remember valstack top on entry
72787 	 *  to restore it later, and switch to using a new function in comp_ctx.
72788 	 */
72789 
72790 	entry_top = duk_get_top(thr);
72791 	DUK_DDD(DUK_DDDPRINT("before func: entry_top=%ld, curr_tok.start_offset=%ld",
72792 	                     (long) entry_top, (long) comp_ctx->curr_token.start_offset));
72793 
72794 	duk_memcpy(&old_func, &comp_ctx->curr_func, sizeof(duk_compiler_func));
72795 
72796 	duk_memzero(&comp_ctx->curr_func, sizeof(duk_compiler_func));
72797 	duk__init_func_valstack_slots(comp_ctx);
72798 	DUK_ASSERT(comp_ctx->curr_func.num_formals == 0);
72799 
72800 	/* inherit initial strictness from parent */
72801 	comp_ctx->curr_func.is_strict = old_func.is_strict;
72802 
72803 	/* XXX: It might be better to just store the flags into the curr_func
72804 	 * struct and use them as is without this flag interpretation step
72805 	 * here.
72806 	 */
72807 	DUK_ASSERT(comp_ctx->curr_func.is_notail == 0);
72808 	comp_ctx->curr_func.is_function = 1;
72809 	DUK_ASSERT(comp_ctx->curr_func.is_eval == 0);
72810 	DUK_ASSERT(comp_ctx->curr_func.is_global == 0);
72811 	comp_ctx->curr_func.is_setget = ((flags & DUK__FUNC_FLAG_GETSET) != 0);
72812 	comp_ctx->curr_func.is_namebinding = !(flags & (DUK__FUNC_FLAG_GETSET |
72813 	                                                DUK__FUNC_FLAG_METDEF |
72814 	                                                DUK__FUNC_FLAG_DECL));  /* no name binding for: declarations, objlit getset, objlit method def */
72815 	comp_ctx->curr_func.is_constructable = !(flags & (DUK__FUNC_FLAG_GETSET |
72816 	                                                  DUK__FUNC_FLAG_METDEF));  /* not constructable: objlit getset, objlit method def */
72817 
72818 	/*
72819 	 *  Parse inner function
72820 	 */
72821 
72822 	duk__parse_func_like_raw(comp_ctx, flags);  /* pushes function template */
72823 
72824 	/* prev_token.start_offset points to the closing brace here; when skipping
72825 	 * we're going to reparse the closing brace to ensure semicolon insertion
72826 	 * etc work as expected.
72827 	 */
72828 	DUK_DDD(DUK_DDDPRINT("after func: prev_tok.start_offset=%ld, curr_tok.start_offset=%ld",
72829 	                     (long) comp_ctx->prev_token.start_offset, (long) comp_ctx->curr_token.start_offset));
72830 	DUK_ASSERT(comp_ctx->lex.input[comp_ctx->prev_token.start_offset] == (duk_uint8_t) DUK_ASC_RCURLY);
72831 
72832 	/* XXX: append primitive */
72833 	DUK_ASSERT(duk_get_length(thr, old_func.funcs_idx) == (duk_size_t) (old_func.fnum_next * 3));
72834 	fnum = old_func.fnum_next++;
72835 
72836 	if (fnum > DUK__MAX_FUNCS) {
72837 		DUK_ERROR_RANGE(comp_ctx->thr, DUK_STR_FUNC_LIMIT);
72838 		DUK_WO_NORETURN(return 0;);
72839 	}
72840 
72841 	/* array writes autoincrement length */
72842 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3));
72843 	duk_push_size_t(thr, comp_ctx->prev_token.start_offset);
72844 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 1));
72845 	duk_push_int(thr, comp_ctx->prev_token.start_line);
72846 	(void) duk_put_prop_index(thr, old_func.funcs_idx, (duk_uarridx_t) (fnum * 3 + 2));
72847 
72848 	/*
72849 	 *  Cleanup: restore original function, restore valstack state.
72850 	 *
72851 	 *  Function declaration handling needs the function name to be pushed
72852 	 *  on the value stack.
72853 	 */
72854 
72855 	if (flags & DUK__FUNC_FLAG_PUSHNAME_PASS1) {
72856 		DUK_ASSERT(comp_ctx->curr_func.h_name != NULL);
72857 		duk_push_hstring(thr, comp_ctx->curr_func.h_name);
72858 		duk_replace(thr, entry_top);
72859 		duk_set_top(thr, entry_top + 1);
72860 	} else {
72861 		duk_set_top(thr, entry_top);
72862 	}
72863 	duk_memcpy((void *) &comp_ctx->curr_func, (void *) &old_func, sizeof(duk_compiler_func));
72864 
72865 	return fnum;
72866 }
72867 
72868 /*
72869  *  Compile input string into an executable function template without
72870  *  arguments.
72871  *
72872  *  The string is parsed as the "Program" production of ECMAScript E5.
72873  *  Compilation context can be either global code or eval code (see E5
72874  *  Sections 14 and 15.1.2.1).
72875  *
72876  *  Input stack:  [ ... filename ]
72877  *  Output stack: [ ... func_template ]
72878  */
72879 
72880 /* XXX: source code property */
72881 
72882 DUK_LOCAL duk_ret_t duk__js_compile_raw(duk_hthread *thr, void *udata) {
72883 	duk_hstring *h_filename;
72884 	duk__compiler_stkstate *comp_stk;
72885 	duk_compiler_ctx *comp_ctx;
72886 	duk_lexer_point *lex_pt;
72887 	duk_compiler_func *func;
72888 	duk_idx_t entry_top;
72889 	duk_bool_t is_strict;
72890 	duk_bool_t is_eval;
72891 	duk_bool_t is_funcexpr;
72892 	duk_small_uint_t flags;
72893 
72894 	DUK_ASSERT(thr != NULL);
72895 	DUK_ASSERT(udata != NULL);
72896 
72897 	/*
72898 	 *  Arguments check
72899 	 */
72900 
72901 	entry_top = duk_get_top(thr);
72902 	DUK_ASSERT(entry_top >= 1);
72903 
72904 	comp_stk = (duk__compiler_stkstate *) udata;
72905 	comp_ctx = &comp_stk->comp_ctx_alloc;
72906 	lex_pt = &comp_stk->lex_pt_alloc;
72907 	DUK_ASSERT(comp_ctx != NULL);
72908 	DUK_ASSERT(lex_pt != NULL);
72909 
72910 	flags = comp_stk->flags;
72911 	is_eval = (flags & DUK_COMPILE_EVAL ? 1 : 0);
72912 	is_strict = (flags & DUK_COMPILE_STRICT ? 1 : 0);
72913 	is_funcexpr = (flags & DUK_COMPILE_FUNCEXPR ? 1 : 0);
72914 
72915 	h_filename = duk_get_hstring(thr, -1);  /* may be undefined */
72916 
72917 	/*
72918 	 *  Init compiler and lexer contexts
72919 	 */
72920 
72921 	func = &comp_ctx->curr_func;
72922 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
72923 	comp_ctx->thr = NULL;
72924 	comp_ctx->h_filename = NULL;
72925 	comp_ctx->prev_token.str1 = NULL;
72926 	comp_ctx->prev_token.str2 = NULL;
72927 	comp_ctx->curr_token.str1 = NULL;
72928 	comp_ctx->curr_token.str2 = NULL;
72929 #endif
72930 
72931 	duk_require_stack(thr, DUK__COMPILE_ENTRY_SLOTS);
72932 
72933 	duk_push_dynamic_buffer(thr, 0);       /* entry_top + 0 */
72934 	duk_push_undefined(thr);               /* entry_top + 1 */
72935 	duk_push_undefined(thr);               /* entry_top + 2 */
72936 	duk_push_undefined(thr);               /* entry_top + 3 */
72937 	duk_push_undefined(thr);               /* entry_top + 4 */
72938 
72939 	comp_ctx->thr = thr;
72940 	comp_ctx->h_filename = h_filename;
72941 	comp_ctx->tok11_idx = entry_top + 1;
72942 	comp_ctx->tok12_idx = entry_top + 2;
72943 	comp_ctx->tok21_idx = entry_top + 3;
72944 	comp_ctx->tok22_idx = entry_top + 4;
72945 	comp_ctx->recursion_limit = DUK_USE_COMPILER_RECLIMIT;
72946 
72947 	/* comp_ctx->lex has been pre-initialized by caller: it has been
72948 	 * zeroed and input/input_length has been set.
72949 	 */
72950 	comp_ctx->lex.thr = thr;
72951 	/* comp_ctx->lex.input and comp_ctx->lex.input_length filled by caller */
72952 	comp_ctx->lex.slot1_idx = comp_ctx->tok11_idx;
72953 	comp_ctx->lex.slot2_idx = comp_ctx->tok12_idx;
72954 	comp_ctx->lex.buf_idx = entry_top + 0;
72955 	comp_ctx->lex.buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, entry_top + 0);
72956 	DUK_ASSERT(DUK_HBUFFER_HAS_DYNAMIC(comp_ctx->lex.buf) && !DUK_HBUFFER_HAS_EXTERNAL(comp_ctx->lex.buf));
72957 	comp_ctx->lex.token_limit = DUK_COMPILER_TOKEN_LIMIT;
72958 
72959 	lex_pt->offset = 0;
72960 	lex_pt->line = 1;
72961 	DUK_LEXER_SETPOINT(&comp_ctx->lex, lex_pt);    /* fills window */
72962 	comp_ctx->curr_token.start_line = 0;  /* needed for line number tracking (becomes prev_token.start_line) */
72963 
72964 	/*
72965 	 *  Initialize function state for a zero-argument function
72966 	 */
72967 
72968 	duk__init_func_valstack_slots(comp_ctx);
72969 	DUK_ASSERT(func->num_formals == 0);
72970 
72971 	if (is_funcexpr) {
72972 		/* Name will be filled from function expression, not by caller.
72973 		 * This case is used by Function constructor and duk_compile()
72974 		 * API with the DUK_COMPILE_FUNCTION option.
72975 		 */
72976 		DUK_ASSERT(func->h_name == NULL);
72977 	} else {
72978 		duk_push_hstring_stridx(thr, (is_eval ? DUK_STRIDX_EVAL :
72979 		                                        DUK_STRIDX_GLOBAL));
72980 		func->h_name = duk_get_hstring(thr, -1);
72981 	}
72982 
72983 	/*
72984 	 *  Parse a function body or a function-like expression, depending
72985 	 *  on flags.
72986 	 */
72987 
72988 	DUK_ASSERT(func->is_setget == 0);
72989 	func->is_strict = (duk_uint8_t) is_strict;
72990 	DUK_ASSERT(func->is_notail == 0);
72991 
72992 	if (is_funcexpr) {
72993 		func->is_function = 1;
72994 		DUK_ASSERT(func->is_eval == 0);
72995 		DUK_ASSERT(func->is_global == 0);
72996 		func->is_namebinding = 1;
72997 		func->is_constructable = 1;
72998 
72999 		duk__advance(comp_ctx);  /* init 'curr_token' */
73000 		duk__advance_expect(comp_ctx, DUK_TOK_FUNCTION);
73001 		(void) duk__parse_func_like_raw(comp_ctx, 0 /*flags*/);
73002 	} else {
73003 		DUK_ASSERT(func->is_function == 0);
73004 		DUK_ASSERT(is_eval == 0 || is_eval == 1);
73005 		func->is_eval = (duk_uint8_t) is_eval;
73006 		func->is_global = (duk_uint8_t) !is_eval;
73007 		DUK_ASSERT(func->is_namebinding == 0);
73008 		DUK_ASSERT(func->is_constructable == 0);
73009 
73010 		duk__parse_func_body(comp_ctx,
73011 		                     1,             /* expect_eof */
73012 		                     1,             /* implicit_return_value */
73013 		                     1,             /* regexp_after (does not matter) */
73014 		                     -1);           /* expect_token */
73015 	}
73016 
73017 	/*
73018 	 *  Convert duk_compiler_func to a function template
73019 	 */
73020 
73021 	duk__convert_to_func_template(comp_ctx);
73022 
73023 	/*
73024 	 *  Wrapping duk_safe_call() will mangle the stack, just return stack top
73025 	 */
73026 
73027 	/* [ ... filename (temps) func ] */
73028 
73029 	return 1;
73030 }
73031 
73032 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) {
73033 	duk__compiler_stkstate comp_stk;
73034 	duk_compiler_ctx *prev_ctx;
73035 	duk_ret_t safe_rc;
73036 
73037 	DUK_ASSERT(thr != NULL);
73038 	DUK_ASSERT(src_buffer != NULL);
73039 
73040 	/* preinitialize lexer state partially */
73041 	duk_memzero(&comp_stk, sizeof(comp_stk));
73042 	comp_stk.flags = flags;
73043 	DUK_LEXER_INITCTX(&comp_stk.comp_ctx_alloc.lex);
73044 	comp_stk.comp_ctx_alloc.lex.input = src_buffer;
73045 	comp_stk.comp_ctx_alloc.lex.input_length = src_length;
73046 	comp_stk.comp_ctx_alloc.lex.flags = flags;  /* Forward flags directly for now. */
73047 
73048 	/* [ ... filename ] */
73049 
73050 	prev_ctx = thr->compile_ctx;
73051 	thr->compile_ctx = &comp_stk.comp_ctx_alloc;  /* for duk_error_augment.c */
73052 	safe_rc = duk_safe_call(thr, duk__js_compile_raw, (void *) &comp_stk /*udata*/, 1 /*nargs*/, 1 /*nrets*/);
73053 	thr->compile_ctx = prev_ctx;  /* must restore reliably before returning */
73054 
73055 	if (safe_rc != DUK_EXEC_SUCCESS) {
73056 		DUK_D(DUK_DPRINT("compilation failed: %!T", duk_get_tval(thr, -1)));
73057 		(void) duk_throw(thr);
73058 		DUK_WO_NORETURN(return;);
73059 	}
73060 
73061 	/* [ ... template ] */
73062 }
73063 
73064 /* automatic undefs */
73065 #undef DUK__ALLOCTEMP
73066 #undef DUK__ALLOCTEMPS
73067 #undef DUK__ALLOW_AUTO_SEMI_ALWAYS
73068 #undef DUK__BC_INITIAL_INSTS
73069 #undef DUK__BP_ADDITIVE
73070 #undef DUK__BP_ASSIGNMENT
73071 #undef DUK__BP_BAND
73072 #undef DUK__BP_BOR
73073 #undef DUK__BP_BXOR
73074 #undef DUK__BP_CALL
73075 #undef DUK__BP_CLOSING
73076 #undef DUK__BP_COMMA
73077 #undef DUK__BP_CONDITIONAL
73078 #undef DUK__BP_EOF
73079 #undef DUK__BP_EQUALITY
73080 #undef DUK__BP_EXPONENTIATION
73081 #undef DUK__BP_FOR_EXPR
73082 #undef DUK__BP_INVALID
73083 #undef DUK__BP_LAND
73084 #undef DUK__BP_LOR
73085 #undef DUK__BP_MEMBER
73086 #undef DUK__BP_MULTIPLICATIVE
73087 #undef DUK__BP_POSTFIX
73088 #undef DUK__BP_RELATIONAL
73089 #undef DUK__BP_SHIFT
73090 #undef DUK__COMPILE_ENTRY_SLOTS
73091 #undef DUK__CONST_MARKER
73092 #undef DUK__DUMP_ISPEC
73093 #undef DUK__DUMP_IVALUE
73094 #undef DUK__EMIT_FLAG_A_IS_SOURCE
73095 #undef DUK__EMIT_FLAG_BC_REGCONST
73096 #undef DUK__EMIT_FLAG_B_IS_TARGET
73097 #undef DUK__EMIT_FLAG_C_IS_TARGET
73098 #undef DUK__EMIT_FLAG_NO_SHUFFLE_A
73099 #undef DUK__EMIT_FLAG_NO_SHUFFLE_B
73100 #undef DUK__EMIT_FLAG_NO_SHUFFLE_C
73101 #undef DUK__EMIT_FLAG_RESERVE_JUMPSLOT
73102 #undef DUK__EXPR_FLAG_ALLOW_EMPTY
73103 #undef DUK__EXPR_FLAG_REJECT_IN
73104 #undef DUK__EXPR_FLAG_REQUIRE_INIT
73105 #undef DUK__EXPR_RBP_MASK
73106 #undef DUK__FUNCTION_BODY_REQUIRE_SLOTS
73107 #undef DUK__FUNCTION_INIT_REQUIRE_SLOTS
73108 #undef DUK__FUNC_FLAG_DECL
73109 #undef DUK__FUNC_FLAG_GETSET
73110 #undef DUK__FUNC_FLAG_METDEF
73111 #undef DUK__FUNC_FLAG_PUSHNAME_PASS1
73112 #undef DUK__FUNC_FLAG_USE_PREVTOKEN
73113 #undef DUK__GETCONST_MAX_CONSTS_CHECK
73114 #undef DUK__GETTEMP
73115 #undef DUK__HAS_TERM
73116 #undef DUK__HAS_VAL
73117 #undef DUK__ISCONST
73118 #undef DUK__ISREG
73119 #undef DUK__ISREG_NOTTEMP
73120 #undef DUK__ISREG_TEMP
73121 #undef DUK__IS_TERMINAL
73122 #undef DUK__IVAL_FLAG_ALLOW_CONST
73123 #undef DUK__IVAL_FLAG_REQUIRE_SHORT
73124 #undef DUK__IVAL_FLAG_REQUIRE_TEMP
73125 #undef DUK__MAX_ARRAY_INIT_VALUES
73126 #undef DUK__MAX_CONSTS
73127 #undef DUK__MAX_FUNCS
73128 #undef DUK__MAX_OBJECT_INIT_PAIRS
73129 #undef DUK__MAX_TEMPS
73130 #undef DUK__MK_LBP
73131 #undef DUK__MK_LBP_FLAGS
73132 #undef DUK__OBJ_LIT_KEY_GET
73133 #undef DUK__OBJ_LIT_KEY_PLAIN
73134 #undef DUK__OBJ_LIT_KEY_SET
73135 #undef DUK__PARSE_EXPR_SLOTS
73136 #undef DUK__PARSE_STATEMENTS_SLOTS
73137 #undef DUK__RECURSION_DECREASE
73138 #undef DUK__RECURSION_INCREASE
73139 #undef DUK__REMOVECONST
73140 #undef DUK__SETTEMP
73141 #undef DUK__SETTEMP_CHECKMAX
73142 #undef DUK__STILL_PROLOGUE
73143 #undef DUK__TOKEN_LBP_BP_MASK
73144 #undef DUK__TOKEN_LBP_FLAG_NO_REGEXP
73145 #undef DUK__TOKEN_LBP_FLAG_TERMINATES
73146 #undef DUK__TOKEN_LBP_FLAG_UNUSED
73147 #undef DUK__TOKEN_LBP_GET_BP
73148 #line 1 "duk_js_executor.c"
73149 /*
73150  *  ECMAScript bytecode executor.
73151  */
73152 
73153 /* #include duk_internal.h -> already included */
73154 
73155 /*
73156  *  Local declarations.
73157  */
73158 
73159 DUK_LOCAL_DECL void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act);
73160 
73161 /*
73162  *  Misc helpers.
73163  */
73164 
73165 /* Forced inline declaration, only applied for performance oriented build. */
73166 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73167 #define DUK__INLINE_PERF
73168 #define DUK__NOINLINE_PERF
73169 #else
73170 #define DUK__INLINE_PERF DUK_ALWAYS_INLINE
73171 #define DUK__NOINLINE_PERF DUK_NOINLINE
73172 #endif
73173 
73174 /* Replace value stack top to value at 'tv_ptr'.  Optimize for
73175  * performance by only applying the net refcount change.
73176  */
73177 #define DUK__REPLACE_TO_TVPTR(thr,tv_ptr) do { \
73178 		duk_hthread *duk__thr; \
73179 		duk_tval *duk__tvsrc; \
73180 		duk_tval *duk__tvdst; \
73181 		duk_tval duk__tvtmp; \
73182 		duk__thr = (thr); \
73183 		duk__tvsrc = DUK_GET_TVAL_NEGIDX(duk__thr, -1); \
73184 		duk__tvdst = (tv_ptr); \
73185 		DUK_TVAL_SET_TVAL(&duk__tvtmp, duk__tvdst); \
73186 		DUK_TVAL_SET_TVAL(duk__tvdst, duk__tvsrc); \
73187 		DUK_TVAL_SET_UNDEFINED(duk__tvsrc);  /* value stack init policy */ \
73188 		duk__thr->valstack_top = duk__tvsrc; \
73189 		DUK_TVAL_DECREF(duk__thr, &duk__tvtmp); \
73190 	} while (0)
73191 
73192 /* XXX: candidate of being an internal shared API call */
73193 #if 0  /* unused */
73194 DUK_LOCAL void duk__push_tvals_incref_only(duk_hthread *thr, duk_tval *tv_src, duk_small_uint_fast_t count) {
73195 	duk_tval *tv_dst;
73196 	duk_size_t copy_size;
73197 	duk_size_t i;
73198 
73199 	tv_dst = thr->valstack_top;
73200 	copy_size = sizeof(duk_tval) * count;
73201 	duk_memcpy((void *) tv_dst, (const void *) tv_src, copy_size);
73202 	for (i = 0; i < count; i++) {
73203 		DUK_TVAL_INCREF(thr, tv_dst);
73204 		tv_dst++;
73205 	}
73206 	thr->valstack_top = tv_dst;
73207 }
73208 #endif
73209 
73210 /*
73211  *  Arithmetic, binary, and logical helpers.
73212  *
73213  *  Note: there is no opcode for logical AND or logical OR; this is on
73214  *  purpose, because the evalution order semantics for them make such
73215  *  opcodes pretty pointless: short circuiting means they are most
73216  *  comfortably implemented as jumps.  However, a logical NOT opcode
73217  *  is useful.
73218  *
73219  *  Note: careful with duk_tval pointers here: they are potentially
73220  *  invalidated by any DECREF and almost any API call.  It's still
73221  *  preferable to work without making a copy but that's not always
73222  *  possible.
73223  */
73224 
73225 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_mod(duk_double_t d1, duk_double_t d2) {
73226 	return (duk_double_t) duk_js_arith_mod((double) d1, (double) d2);
73227 }
73228 
73229 #if defined(DUK_USE_ES7_EXP_OPERATOR)
73230 DUK_LOCAL DUK__INLINE_PERF duk_double_t duk__compute_exp(duk_double_t d1, duk_double_t d2) {
73231 	return (duk_double_t) duk_js_arith_pow((double) d1, (double) d2);
73232 }
73233 #endif
73234 
73235 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) {
73236 	/*
73237 	 *  Addition operator is different from other arithmetic
73238 	 *  operations in that it also provides string concatenation.
73239 	 *  Hence it is implemented separately.
73240 	 *
73241 	 *  There is a fast path for number addition.  Other cases go
73242 	 *  through potentially multiple coercions as described in the
73243 	 *  E5 specification.  It may be possible to reduce the number
73244 	 *  of coercions, but this must be done carefully to preserve
73245 	 *  the exact semantics.
73246 	 *
73247 	 *  E5 Section 11.6.1.
73248 	 *
73249 	 *  Custom types also have special behavior implemented here.
73250 	 */
73251 
73252 	duk_double_union du;
73253 
73254 	DUK_ASSERT(thr != NULL);
73255 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73256 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73257 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73258 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73259 
73260 	/*
73261 	 *  Fast paths
73262 	 */
73263 
73264 #if defined(DUK_USE_FASTINT)
73265 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73266 		duk_int64_t v1, v2, v3;
73267 		duk_int32_t v3_hi;
73268 		duk_tval *tv_z;
73269 
73270 		/* Input values are signed 48-bit so we can detect overflow
73271 		 * reliably from high bits or just a comparison.
73272 		 */
73273 
73274 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73275 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73276 		v3 = v1 + v2;
73277 		v3_hi = (duk_int32_t) (v3 >> 32);
73278 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
73279 			tv_z = thr->valstack_bottom + idx_z;
73280 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
73281 			return;
73282 		} else {
73283 			/* overflow, fall through */
73284 			;
73285 		}
73286 	}
73287 #endif  /* DUK_USE_FASTINT */
73288 
73289 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
73290 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
73291 		duk_tval *tv_z;
73292 #endif
73293 
73294 		du.d = DUK_TVAL_GET_NUMBER(tv_x) + DUK_TVAL_GET_NUMBER(tv_y);
73295 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73296 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73297 		duk_replace(thr, (duk_idx_t) idx_z);
73298 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73299 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
73300 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73301 		tv_z = thr->valstack_bottom + idx_z;
73302 		DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
73303 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73304 		return;
73305 	}
73306 
73307 	/*
73308 	 *  Slow path: potentially requires function calls for coercion
73309 	 */
73310 
73311 	duk_push_tval(thr, tv_x);
73312 	duk_push_tval(thr, tv_y);
73313 	duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* side effects -> don't use tv_x, tv_y after */
73314 	duk_to_primitive(thr, -1, DUK_HINT_NONE);
73315 
73316 	/* Since Duktape 2.x plain buffers are treated like ArrayBuffer. */
73317 	if (duk_is_string(thr, -2) || duk_is_string(thr, -1)) {
73318 		/* Symbols shouldn't technically be handled here, but should
73319 		 * go into the default ToNumber() coercion path instead and
73320 		 * fail there with a TypeError.  However, there's a ToString()
73321 		 * in duk_concat_2() which also fails with TypeError so no
73322 		 * explicit check is needed.
73323 		 */
73324 		duk_concat_2(thr);  /* [... s1 s2] -> [... s1+s2] */
73325 	} else {
73326 		duk_double_t d1, d2;
73327 
73328 		d1 = duk_to_number_m2(thr);
73329 		d2 = duk_to_number_m1(thr);
73330 		DUK_ASSERT(duk_is_number(thr, -2));
73331 		DUK_ASSERT(duk_is_number(thr, -1));
73332 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
73333 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
73334 
73335 		du.d = d1 + d2;
73336 		duk_pop_2_unsafe(thr);
73337 		duk_push_number(thr, du.d);  /* will NaN normalize result */
73338 	}
73339 	duk_replace(thr, (duk_idx_t) idx_z);  /* side effects */
73340 }
73341 
73342 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) {
73343 	/*
73344 	 *  Arithmetic operations other than '+' have number-only semantics
73345 	 *  and are implemented here.  The separate switch-case here means a
73346 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
73347 	 *
73348 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
73349 	 */
73350 
73351 	duk_double_t d1, d2;
73352 	duk_double_union du;
73353 	duk_small_uint_fast_t opcode_shifted;
73354 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
73355 	duk_tval *tv_z;
73356 #endif
73357 
73358 	DUK_ASSERT(thr != NULL);
73359 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73360 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73361 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73362 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73363 
73364 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
73365 
73366 #if defined(DUK_USE_FASTINT)
73367 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73368 		duk_int64_t v1, v2, v3;
73369 		duk_int32_t v3_hi;
73370 
73371 		v1 = DUK_TVAL_GET_FASTINT(tv_x);
73372 		v2 = DUK_TVAL_GET_FASTINT(tv_y);
73373 
73374 		switch (opcode_shifted) {
73375 		case DUK_OP_SUB >> 2: {
73376 			v3 = v1 - v2;
73377 			break;
73378 		}
73379 		case DUK_OP_MUL >> 2: {
73380 			/* Must ensure result is 64-bit (no overflow); a
73381 			 * simple and sufficient fast path is to allow only
73382 			 * 32-bit inputs.  Avoid zero inputs to avoid
73383 			 * negative zero issues (-1 * 0 = -0, for instance).
73384 			 */
73385 			if (v1 >= DUK_I64_CONSTANT(-0x80000000) && v1 <= DUK_I64_CONSTANT(0x7fffffff) && v1 != 0 &&
73386 			    v2 >= DUK_I64_CONSTANT(-0x80000000) && v2 <= DUK_I64_CONSTANT(0x7fffffff) && v2 != 0) {
73387 				v3 = v1 * v2;
73388 			} else {
73389 				goto skip_fastint;
73390 			}
73391 			break;
73392 		}
73393 		case DUK_OP_DIV >> 2: {
73394 			/* Don't allow a zero divisor.  Fast path check by
73395 			 * "verifying" with multiplication.  Also avoid zero
73396 			 * dividend to avoid negative zero issues (0 / -1 = -0
73397 			 * for instance).
73398 			 */
73399 			if (v1 == 0 || v2 == 0) {
73400 				goto skip_fastint;
73401 			}
73402 			v3 = v1 / v2;
73403 			if (v3 * v2 != v1) {
73404 				goto skip_fastint;
73405 			}
73406 			break;
73407 		}
73408 		case DUK_OP_MOD >> 2: {
73409 			/* Don't allow a zero divisor.  Restrict both v1 and
73410 			 * v2 to positive values to avoid compiler specific
73411 			 * behavior.
73412 			 */
73413 			if (v1 < 1 || v2 < 1) {
73414 				goto skip_fastint;
73415 			}
73416 			v3 = v1 % v2;
73417 			DUK_ASSERT(v3 >= 0);
73418 			DUK_ASSERT(v3 < v2);
73419 			DUK_ASSERT(v1 - (v1 / v2) * v2 == v3);
73420 			break;
73421 		}
73422 		default: {
73423 			/* Possible with DUK_OP_EXP. */
73424 			goto skip_fastint;
73425 		}
73426 		}
73427 
73428 		v3_hi = (duk_int32_t) (v3 >> 32);
73429 		if (DUK_LIKELY(v3_hi >= DUK_I64_CONSTANT(-0x8000) && v3_hi <= DUK_I64_CONSTANT(0x7fff))) {
73430 			tv_z = thr->valstack_bottom + idx_z;
73431 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, v3);  /* side effects */
73432 			return;
73433 		}
73434 		/* fall through if overflow etc */
73435 	}
73436  skip_fastint:
73437 #endif  /* DUK_USE_FASTINT */
73438 
73439 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
73440 		/* fast path */
73441 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
73442 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
73443 	} else {
73444 		duk_push_tval(thr, tv_x);
73445 		duk_push_tval(thr, tv_y);
73446 		d1 = duk_to_number_m2(thr);  /* side effects */
73447 		d2 = duk_to_number_m1(thr);
73448 		DUK_ASSERT(duk_is_number(thr, -2));
73449 		DUK_ASSERT(duk_is_number(thr, -1));
73450 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d1);
73451 		DUK_ASSERT_DOUBLE_IS_NORMALIZED(d2);
73452 		duk_pop_2_unsafe(thr);
73453 	}
73454 
73455 	switch (opcode_shifted) {
73456 	case DUK_OP_SUB >> 2: {
73457 		du.d = d1 - d2;
73458 		break;
73459 	}
73460 	case DUK_OP_MUL >> 2: {
73461 		du.d = d1 * d2;
73462 		break;
73463 	}
73464 	case DUK_OP_DIV >> 2: {
73465 		/* Division-by-zero is undefined behavior, so
73466 		 * rely on a helper.
73467 		 */
73468 		du.d = duk_double_div(d1, d2);
73469 		break;
73470 	}
73471 	case DUK_OP_MOD >> 2: {
73472 		du.d = duk__compute_mod(d1, d2);
73473 		break;
73474 	}
73475 #if defined(DUK_USE_ES7_EXP_OPERATOR)
73476 	case DUK_OP_EXP >> 2: {
73477 		du.d = duk__compute_exp(d1, d2);
73478 		break;
73479 	}
73480 #endif
73481 	default: {
73482 		DUK_UNREACHABLE();
73483 		du.d = DUK_DOUBLE_NAN;  /* should not happen */
73484 		break;
73485 	}
73486 	}
73487 
73488 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73489 	duk_push_number(thr, du.d);  /* will NaN normalize result */
73490 	duk_replace(thr, (duk_idx_t) idx_z);
73491 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73492 	/* important to use normalized NaN with 8-byte tagged types */
73493 	DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);
73494 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73495 	tv_z = thr->valstack_bottom + idx_z;
73496 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, du.d);  /* side effects */
73497 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73498 }
73499 
73500 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) {
73501 	/*
73502 	 *  Binary bitwise operations use different coercions (ToInt32, ToUint32)
73503 	 *  depending on the operation.  We coerce the arguments first using
73504 	 *  ToInt32(), and then cast to an 32-bit value if necessary.  Note that
73505 	 *  such casts must be correct even if there is no native 32-bit type
73506 	 *  (e.g., duk_int32_t and duk_uint32_t are 64-bit).
73507 	 *
73508 	 *  E5 Sections 11.10, 11.7.1, 11.7.2, 11.7.3
73509 	 */
73510 
73511 	duk_int32_t i1, i2, i3;
73512 	duk_uint32_t u1, u2, u3;
73513 #if defined(DUK_USE_FASTINT)
73514 	duk_int64_t fi3;
73515 #else
73516 	duk_double_t d3;
73517 #endif
73518 	duk_small_uint_fast_t opcode_shifted;
73519 #if defined(DUK_USE_FASTINT) || !defined(DUK_USE_EXEC_PREFER_SIZE)
73520 	duk_tval *tv_z;
73521 #endif
73522 
73523 	DUK_ASSERT(thr != NULL);
73524 	DUK_ASSERT(tv_x != NULL);  /* may be reg or const */
73525 	DUK_ASSERT(tv_y != NULL);  /* may be reg or const */
73526 	DUK_ASSERT_DISABLE(idx_z >= 0);  /* unsigned */
73527 	DUK_ASSERT((duk_uint_t) idx_z < (duk_uint_t) duk_get_top(thr));
73528 
73529 	opcode_shifted = opcode >> 2;  /* Get base opcode without reg/const modifiers. */
73530 
73531 #if defined(DUK_USE_FASTINT)
73532 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
73533 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_x);
73534 		i2 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv_y);
73535 	}
73536 	else
73537 #endif  /* DUK_USE_FASTINT */
73538 	{
73539 		duk_push_tval(thr, tv_x);
73540 		duk_push_tval(thr, tv_y);
73541 		i1 = duk_to_int32(thr, -2);
73542 		i2 = duk_to_int32(thr, -1);
73543 		duk_pop_2_unsafe(thr);
73544 	}
73545 
73546 	switch (opcode_shifted) {
73547 	case DUK_OP_BAND >> 2: {
73548 		i3 = i1 & i2;
73549 		break;
73550 	}
73551 	case DUK_OP_BOR >> 2: {
73552 		i3 = i1 | i2;
73553 		break;
73554 	}
73555 	case DUK_OP_BXOR >> 2: {
73556 		i3 = i1 ^ i2;
73557 		break;
73558 	}
73559 	case DUK_OP_BASL >> 2: {
73560 		/* Signed shift, named "arithmetic" (asl) because the result
73561 		 * is signed, e.g. 4294967295 << 1 -> -2.  Note that result
73562 		 * must be masked.
73563 		 */
73564 
73565 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73566 		i3 = (duk_int32_t) (((duk_uint32_t) i1) << (u2 & 0x1fUL));  /* E5 Section 11.7.1, steps 7 and 8 */
73567 		i3 = i3 & ((duk_int32_t) 0xffffffffUL);                     /* Note: left shift, should mask */
73568 		break;
73569 	}
73570 	case DUK_OP_BASR >> 2: {
73571 		/* signed shift */
73572 
73573 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73574 		i3 = i1 >> (u2 & 0x1fUL);                      /* E5 Section 11.7.2, steps 7 and 8 */
73575 		break;
73576 	}
73577 	case DUK_OP_BLSR >> 2: {
73578 		/* unsigned shift */
73579 
73580 		u1 = ((duk_uint32_t) i1) & 0xffffffffUL;
73581 		u2 = ((duk_uint32_t) i2) & 0xffffffffUL;
73582 
73583 		/* special result value handling */
73584 		u3 = u1 >> (u2 & 0x1fUL);     /* E5 Section 11.7.2, steps 7 and 8 */
73585 #if defined(DUK_USE_FASTINT)
73586 		fi3 = (duk_int64_t) u3;
73587 		goto fastint_result_set;
73588 #else
73589 		d3 = (duk_double_t) u3;
73590 		goto result_set;
73591 #endif
73592 	}
73593 	default: {
73594 		DUK_UNREACHABLE();
73595 		i3 = 0;  /* should not happen */
73596 		break;
73597 	}
73598 	}
73599 
73600 #if defined(DUK_USE_FASTINT)
73601 	/* Result is always fastint compatible. */
73602 	/* XXX: Set 32-bit result (but must then handle signed and
73603 	 * unsigned results separately).
73604 	 */
73605 	fi3 = (duk_int64_t) i3;
73606 
73607  fastint_result_set:
73608 	tv_z = thr->valstack_bottom + idx_z;
73609 	DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_z, fi3);  /* side effects */
73610 #else  /* DUK_USE_FASTINT */
73611 	d3 = (duk_double_t) i3;
73612 
73613  result_set:
73614 	DUK_ASSERT(!DUK_ISNAN(d3));            /* 'd3' is never NaN, so no need to normalize */
73615 	DUK_ASSERT_DOUBLE_IS_NORMALIZED(d3);   /* always normalized */
73616 
73617 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73618 	duk_push_number(thr, d3);  /* would NaN normalize result, but unnecessary */
73619 	duk_replace(thr, (duk_idx_t) idx_z);
73620 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73621 	tv_z = thr->valstack_bottom + idx_z;
73622 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_z, d3);  /* side effects */
73623 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73624 #endif  /* DUK_USE_FASTINT */
73625 }
73626 
73627 /* In-place unary operation. */
73628 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) {
73629 	/*
73630 	 *  Arithmetic operations other than '+' have number-only semantics
73631 	 *  and are implemented here.  The separate switch-case here means a
73632 	 *  "double dispatch" of the arithmetic opcode, but saves code space.
73633 	 *
73634 	 *  E5 Sections 11.5, 11.5.1, 11.5.2, 11.5.3, 11.6, 11.6.1, 11.6.2, 11.6.3.
73635 	 */
73636 
73637 	duk_tval *tv;
73638 	duk_double_t d1;
73639 	duk_double_union du;
73640 
73641 	DUK_ASSERT(thr != NULL);
73642 	DUK_ASSERT(opcode == DUK_OP_UNM || opcode == DUK_OP_UNP);
73643 	DUK_ASSERT_DISABLE(idx_src >= 0);
73644 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73645 
73646 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73647 
73648 #if defined(DUK_USE_FASTINT)
73649 	if (DUK_TVAL_IS_FASTINT(tv)) {
73650 		duk_int64_t v1, v2;
73651 
73652 		v1 = DUK_TVAL_GET_FASTINT(tv);
73653 		if (opcode == DUK_OP_UNM) {
73654 			/* The smallest fastint is no longer 48-bit when
73655 			 * negated.  Positive zero becames negative zero
73656 			 * (cannot be represented) when negated.
73657 			 */
73658 			if (DUK_LIKELY(v1 != DUK_FASTINT_MIN && v1 != 0)) {
73659 				v2 = -v1;
73660 				tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73661 				DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
73662 				return;
73663 			}
73664 		} else {
73665 			/* ToNumber() for a fastint is a no-op. */
73666 			DUK_ASSERT(opcode == DUK_OP_UNP);
73667 			v2 = v1;
73668 			tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73669 			DUK_TVAL_SET_FASTINT_UPDREF(thr, tv, v2);
73670 			return;
73671 		}
73672 		/* fall through if overflow etc */
73673 	}
73674 #endif  /* DUK_USE_FASTINT */
73675 
73676 	if (DUK_TVAL_IS_NUMBER(tv)) {
73677 		d1 = DUK_TVAL_GET_NUMBER(tv);
73678 	} else {
73679 		d1 = duk_to_number_tval(thr, tv);  /* side effects */
73680 	}
73681 
73682 	if (opcode == DUK_OP_UNP) {
73683 		/* ToNumber() for a double is a no-op, but unary plus is
73684 		 * used to force a fastint check so do that here.
73685 		 */
73686 		du.d = d1;
73687 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73688 #if defined(DUK_USE_FASTINT)
73689 		tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73690 		DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);  /* always 'fast', i.e. inlined */
73691 		return;
73692 #endif
73693 	} else {
73694 		DUK_ASSERT(opcode == DUK_OP_UNM);
73695 		du.d = -d1;
73696 		DUK_DBLUNION_NORMALIZE_NAN_CHECK(&du);  /* mandatory if du.d is a NaN */
73697 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
73698 	}
73699 
73700 	/* XXX: size optimize: push+replace? */
73701 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73702 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv, du.d);
73703 }
73704 
73705 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) {
73706 	/*
73707 	 *  E5 Section 11.4.8
73708 	 */
73709 
73710 	duk_tval *tv;
73711 	duk_int32_t i1, i2;
73712 
73713 	DUK_ASSERT(thr != NULL);
73714 	DUK_ASSERT_DISABLE(idx_src >= 0);
73715 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73716 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
73717 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
73718 
73719 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73720 
73721 #if defined(DUK_USE_FASTINT)
73722 	if (DUK_TVAL_IS_FASTINT(tv)) {
73723 		i1 = (duk_int32_t) DUK_TVAL_GET_FASTINT_I32(tv);
73724 	}
73725 	else
73726 #endif  /* DUK_USE_FASTINT */
73727 	{
73728 		duk_push_tval(thr, tv);
73729 		i1 = duk_to_int32(thr, -1);  /* side effects */
73730 		duk_pop_unsafe(thr);
73731 	}
73732 
73733 	/* Result is always fastint compatible. */
73734 	i2 = ~i1;
73735 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73736 	DUK_TVAL_SET_I32_UPDREF(thr, tv, i2);  /* side effects */
73737 }
73738 
73739 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) {
73740 	/*
73741 	 *  E5 Section 11.4.9
73742 	 */
73743 
73744 	duk_tval *tv;
73745 	duk_bool_t res;
73746 
73747 	DUK_ASSERT(thr != NULL);
73748 	DUK_ASSERT_DISABLE(idx_src >= 0);
73749 	DUK_ASSERT_DISABLE(idx_dst >= 0);
73750 	DUK_ASSERT((duk_uint_t) idx_src < (duk_uint_t) duk_get_top(thr));
73751 	DUK_ASSERT((duk_uint_t) idx_dst < (duk_uint_t) duk_get_top(thr));
73752 
73753 	/* ToBoolean() does not require any operations with side effects so
73754 	 * we can do it efficiently.  For footprint it would be better to use
73755 	 * duk_js_toboolean() and then push+replace to the result slot.
73756 	 */
73757 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_src);
73758 	res = duk_js_toboolean(tv);  /* does not modify 'tv' */
73759 	DUK_ASSERT(res == 0 || res == 1);
73760 	res ^= 1;
73761 	tv = DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst);
73762 	/* XXX: size optimize: push+replace? */
73763 	DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv, res);  /* side effects */
73764 }
73765 
73766 /* XXX: size optimized variant */
73767 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) {
73768 	duk_double_t x, y, z;
73769 
73770 	/* Two lowest bits of opcode are used to distinguish
73771 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
73772 	 */
73773 	DUK_ASSERT((DUK_OP_PREINCR & 0x03) == 0x00);
73774 	DUK_ASSERT((DUK_OP_PREDECR & 0x03) == 0x01);
73775 	DUK_ASSERT((DUK_OP_POSTINCR & 0x03) == 0x02);
73776 	DUK_ASSERT((DUK_OP_POSTDECR & 0x03) == 0x03);
73777 
73778 #if defined(DUK_USE_FASTINT)
73779 	if (DUK_TVAL_IS_FASTINT(tv_src)) {
73780 		duk_int64_t x_fi, y_fi, z_fi;
73781 		x_fi = DUK_TVAL_GET_FASTINT(tv_src);
73782 		if (op & 0x01) {
73783 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MIN)) {
73784 				goto skip_fastint;
73785 			}
73786 			y_fi = x_fi - 1;
73787 		} else {
73788 			if (DUK_UNLIKELY(x_fi == DUK_FASTINT_MAX)) {
73789 				goto skip_fastint;
73790 			}
73791 			y_fi = x_fi + 1;
73792 		}
73793 
73794 		DUK_TVAL_SET_FASTINT(tv_src, y_fi);  /* no need for refcount update */
73795 
73796 		z_fi = (op & 0x02) ? x_fi : y_fi;
73797 		DUK_TVAL_SET_FASTINT_UPDREF(thr, tv_dst, z_fi);  /* side effects */
73798 		return;
73799 	}
73800  skip_fastint:
73801 #endif
73802 	if (DUK_TVAL_IS_NUMBER(tv_src)) {
73803 		/* Fast path for the case where the register
73804 		 * is a number (e.g. loop counter).
73805 		 */
73806 
73807 		x = DUK_TVAL_GET_NUMBER(tv_src);
73808 		if (op & 0x01) {
73809 			y = x - 1.0;
73810 		} else {
73811 			y = x + 1.0;
73812 		}
73813 
73814 		DUK_TVAL_SET_NUMBER(tv_src, y);  /* no need for refcount update */
73815 	} else {
73816 		/* Preserve duk_tval pointer(s) across a potential valstack
73817 		 * resize by converting them into offsets temporarily.
73818 		 */
73819 		duk_idx_t bc;
73820 		duk_size_t off_dst;
73821 
73822 		off_dst = (duk_size_t) ((duk_uint8_t *) tv_dst - (duk_uint8_t *) thr->valstack_bottom);
73823 		bc = (duk_idx_t) (tv_src - thr->valstack_bottom);  /* XXX: pass index explicitly? */
73824 		tv_src = NULL;  /* no longer referenced */
73825 
73826 		x = duk_to_number(thr, bc);
73827 		if (op & 0x01) {
73828 			y = x - 1.0;
73829 		} else {
73830 			y = x + 1.0;
73831 		}
73832 
73833 		duk_push_number(thr, y);
73834 		duk_replace(thr, bc);
73835 
73836 		tv_dst = (duk_tval *) (void *) (((duk_uint8_t *) thr->valstack_bottom) + off_dst);
73837 	}
73838 
73839 	z = (op & 0x02) ? x : y;
73840 	DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);  /* side effects */
73841 }
73842 
73843 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) {
73844 	duk_activation *act;
73845 	duk_double_t x, y;
73846 	duk_hstring *name;
73847 
73848 	/* XXX: The pre/post inc/dec for an identifier lookup is
73849 	 * missing the important fast path where the identifier
73850 	 * has a storage location e.g. in a scope object so that
73851 	 * it can be updated in-place.  In particular, the case
73852 	 * where the identifier has a storage location AND the
73853 	 * previous value is a number should be optimized because
73854 	 * it's side effect free.
73855 	 */
73856 
73857 	/* Two lowest bits of opcode are used to distinguish
73858 	 * variants.  Bit 0 = inc(0)/dec(1), bit 1 = pre(0)/post(1).
73859 	 */
73860 	DUK_ASSERT((DUK_OP_PREINCV & 0x03) == 0x00);
73861 	DUK_ASSERT((DUK_OP_PREDECV & 0x03) == 0x01);
73862 	DUK_ASSERT((DUK_OP_POSTINCV & 0x03) == 0x02);
73863 	DUK_ASSERT((DUK_OP_POSTDECV & 0x03) == 0x03);
73864 
73865 	DUK_ASSERT(DUK_TVAL_IS_STRING(tv_id));
73866 	name = DUK_TVAL_GET_STRING(tv_id);
73867 	DUK_ASSERT(name != NULL);
73868 	act = thr->callstack_curr;
73869 	(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [ ... val this ] */
73870 
73871 	/* XXX: Fastint fast path would be useful here.  Also fastints
73872 	 * now lose their fastint status in current handling which is
73873 	 * not intuitive.
73874 	 */
73875 
73876 	x = duk_to_number_m2(thr);
73877 	if (op & 0x01) {
73878 		y = x - 1.0;
73879 	} else {
73880 		y = x + 1.0;
73881 	}
73882 
73883 	/* [... x this] */
73884 
73885 	if (op & 0x02) {
73886 		duk_push_number(thr, y);  /* -> [ ... x this y ] */
73887 		DUK_ASSERT(act == thr->callstack_curr);
73888 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
73889 		duk_pop_2_unsafe(thr);  /* -> [ ... x ] */
73890 	} else {
73891 		duk_pop_2_unsafe(thr);  /* -> [ ... ] */
73892 		duk_push_number(thr, y);  /* -> [ ... y ] */
73893 		DUK_ASSERT(act == thr->callstack_curr);
73894 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(thr, -1), is_strict);
73895 	}
73896 
73897 #if defined(DUK_USE_EXEC_PREFER_SIZE)
73898 	duk_replace(thr, (duk_idx_t) idx_dst);
73899 #else  /* DUK_USE_EXEC_PREFER_SIZE */
73900 	DUK__REPLACE_TO_TVPTR(thr, DUK_GET_TVAL_POSIDX(thr, (duk_idx_t) idx_dst));
73901 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
73902 }
73903 
73904 /*
73905  *  Longjmp and other control flow transfer for the bytecode executor.
73906  *
73907  *  The longjmp handler can handle all longjmp types: error, yield, and
73908  *  resume (pseudotypes are never actually thrown).
73909  *
73910  *  Error policy for longjmp: should not ordinarily throw errors; if errors
73911  *  occur (e.g. due to out-of-memory) they bubble outwards rather than being
73912  *  handled recursively.
73913  */
73914 
73915 #define DUK__LONGJMP_RESTART   0  /* state updated, restart bytecode execution */
73916 #define DUK__LONGJMP_RETHROW   1  /* exit bytecode executor by rethrowing an error to caller */
73917 
73918 #define DUK__RETHAND_RESTART   0  /* state updated, restart bytecode execution */
73919 #define DUK__RETHAND_FINISHED  1  /* exit bytecode execution with return value */
73920 
73921 /* XXX: optimize reconfig valstack operations so that resize, clamp, and setting
73922  * top are combined into one pass.
73923  */
73924 
73925 /* Reconfigure value stack for return to an ECMAScript function at
73926  * callstack top (caller unwinds).
73927  */
73928 DUK_LOCAL void duk__reconfig_valstack_ecma_return(duk_hthread *thr) {
73929 	duk_activation *act;
73930 	duk_hcompfunc *h_func;
73931 	duk_idx_t clamp_top;
73932 
73933 	DUK_ASSERT(thr != NULL);
73934 	act = thr->callstack_curr;
73935 	DUK_ASSERT(act != NULL);
73936 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
73937 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
73938 
73939 	/* Clamp so that values at 'clamp_top' and above are wiped and won't
73940 	 * retain reachable garbage.  Then extend to 'nregs' because we're
73941 	 * returning to an ECMAScript function.
73942 	 */
73943 
73944 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
73945 
73946 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
73947 	DUK_ASSERT(act->retval_byteoff >= act->bottom_byteoff);
73948 	clamp_top = (duk_idx_t) ((act->retval_byteoff - act->bottom_byteoff + sizeof(duk_tval)) / sizeof(duk_tval));  /* +1 = one retval */
73949 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
73950 
73951 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73952 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73953 
73954 	/* XXX: a best effort shrink check would be OK here */
73955 }
73956 
73957 /* Reconfigure value stack for an ECMAScript catcher.  Use topmost catcher
73958  * in 'act'.
73959  */
73960 DUK_LOCAL void duk__reconfig_valstack_ecma_catcher(duk_hthread *thr, duk_activation *act) {
73961 	duk_catcher *cat;
73962 	duk_hcompfunc *h_func;
73963 	duk_size_t idx_bottom;
73964 	duk_idx_t clamp_top;
73965 
73966 	DUK_ASSERT(thr != NULL);
73967 	DUK_ASSERT(act != NULL);
73968 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
73969 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
73970 	cat = act->cat;
73971 	DUK_ASSERT(cat != NULL);
73972 
73973 	h_func = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
73974 
73975 	thr->valstack_bottom = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
73976 	idx_bottom = (duk_size_t) (thr->valstack_bottom - thr->valstack);
73977 	DUK_ASSERT(cat->idx_base >= idx_bottom);
73978 	clamp_top = (duk_idx_t) (cat->idx_base - idx_bottom + 2);  /* +2 = catcher value, catcher lj_type */
73979 	duk_set_top_and_wipe(thr, h_func->nregs, clamp_top);
73980 
73981 	DUK_ASSERT((duk_uint8_t *) thr->valstack_end >= (duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73982 	thr->valstack_end = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->reserve_byteoff);
73983 
73984 	/* XXX: a best effort shrink check would be OK here */
73985 }
73986 
73987 /* Set catcher regs: idx_base+0 = value, idx_base+1 = lj_type.
73988  * No side effects.
73989  */
73990 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) {
73991 	duk_tval *tv1;
73992 
73993 	DUK_ASSERT(thr != NULL);
73994 	DUK_ASSERT(tv_val_unstable != NULL);
73995 
73996 	tv1 = thr->valstack + cat->idx_base;
73997 	DUK_ASSERT(tv1 < thr->valstack_top);
73998 	DUK_TVAL_SET_TVAL_UPDREF_NORZ(thr, tv1, tv_val_unstable);
73999 
74000 	tv1++;
74001 	DUK_ASSERT(tv1 == thr->valstack + cat->idx_base + 1);
74002 	DUK_ASSERT(tv1 < thr->valstack_top);
74003 	DUK_TVAL_SET_U32_UPDREF_NORZ(thr, tv1, (duk_uint32_t) lj_type);
74004 }
74005 
74006 DUK_LOCAL void duk__handle_catch(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
74007 	duk_activation *act;
74008 	duk_catcher *cat;
74009 
74010 	DUK_ASSERT(thr != NULL);
74011 	DUK_ASSERT(tv_val_unstable != NULL);
74012 
74013 	act = thr->callstack_curr;
74014 	DUK_ASSERT(act != NULL);
74015 	DUK_ASSERT(act->cat != NULL);
74016 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74017 
74018 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74019 
74020 	DUK_ASSERT(thr->callstack_top >= 1);
74021 	DUK_ASSERT(thr->callstack_curr != NULL);
74022 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74023 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74024 
74025 	DUK_ASSERT(thr->callstack_top >= 1);
74026 	DUK_ASSERT(act == thr->callstack_curr);
74027 	DUK_ASSERT(act != NULL);
74028 	duk__reconfig_valstack_ecma_catcher(thr, act);
74029 
74030 	DUK_ASSERT(thr->callstack_top >= 1);
74031 	DUK_ASSERT(act == thr->callstack_curr);
74032 	DUK_ASSERT(act != NULL);
74033 	cat = act->cat;
74034 	DUK_ASSERT(cat != NULL);
74035 
74036 	act->curr_pc = cat->pc_base + 0;  /* +0 = catch */
74037 
74038 	/*
74039 	 *  If entering a 'catch' block which requires an automatic
74040 	 *  catch variable binding, create the lexical environment.
74041 	 *
74042 	 *  The binding is mutable (= writable) but not deletable.
74043 	 *  Step 4 for the catch production in E5 Section 12.14;
74044 	 *  no value is given for CreateMutableBinding 'D' argument,
74045 	 *  which implies the binding is not deletable.
74046 	 */
74047 
74048 	if (DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat)) {
74049 		duk_hdecenv *new_env;
74050 
74051 		DUK_DDD(DUK_DDDPRINT("catcher has an automatic catch binding"));
74052 
74053 		DUK_ASSERT(thr->callstack_top >= 1);
74054 		DUK_ASSERT(act == thr->callstack_curr);
74055 		DUK_ASSERT(act != NULL);
74056 
74057 		if (act->lex_env == NULL) {
74058 			DUK_ASSERT(act->var_env == NULL);
74059 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
74060 
74061 			duk_js_init_activation_environment_records_delayed(thr, act);
74062 			DUK_ASSERT(act == thr->callstack_curr);
74063 			DUK_ASSERT(act != NULL);
74064 		}
74065 		DUK_ASSERT(act->lex_env != NULL);
74066 		DUK_ASSERT(act->var_env != NULL);
74067 		DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74068 
74069 		/* XXX: If an out-of-memory happens here, longjmp state asserts
74070 		 * will be triggered at present and a try-catch fails to catch.
74071 		 * That's not sandboxing fatal (C API protected calls are what
74072 		 * matters), and script catch code can immediately throw anyway
74073 		 * for almost any operation.
74074 		 */
74075 		new_env = duk_hdecenv_alloc(thr,
74076 		                            DUK_HOBJECT_FLAG_EXTENSIBLE |
74077 		                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
74078 		DUK_ASSERT(new_env != NULL);
74079 		duk_push_hobject(thr, (duk_hobject *) new_env);
74080 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
74081 		DUK_DDD(DUK_DDDPRINT("new_env allocated: %!iO", (duk_heaphdr *) new_env));
74082 
74083 		/* Note: currently the catch binding is handled without a register
74084 		 * binding because we don't support dynamic register bindings (they
74085 		 * must be fixed for an entire function).  So, there is no need to
74086 		 * record regbases etc.
74087 		 */
74088 
74089 		/* XXX: duk_xdef_prop() may cause an out-of-memory, see above. */
74090 		DUK_ASSERT(cat->h_varname != NULL);
74091 		duk_push_hstring(thr, cat->h_varname);
74092 		duk_push_tval(thr, thr->valstack + cat->idx_base);
74093 		duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_W);  /* writable, not configurable */
74094 
74095 		DUK_ASSERT(act == thr->callstack_curr);
74096 		DUK_ASSERT(act != NULL);
74097 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, act->lex_env);
74098 		act->lex_env = (duk_hobject *) new_env;
74099 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);  /* reachable through activation */
74100 		/* Net refcount change to act->lex_env is 0: incref for new_env's
74101 		 * prototype, decref for act->lex_env overwrite.
74102 		 */
74103 
74104 		DUK_CAT_SET_LEXENV_ACTIVE(cat);
74105 
74106 		duk_pop_unsafe(thr);
74107 
74108 		DUK_DDD(DUK_DDDPRINT("new_env finished: %!iO", (duk_heaphdr *) new_env));
74109 	}
74110 
74111 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
74112 }
74113 
74114 DUK_LOCAL void duk__handle_finally(duk_hthread *thr, duk_tval *tv_val_unstable, duk_small_uint_t lj_type) {
74115 	duk_activation *act;
74116 	duk_catcher *cat;
74117 
74118 	DUK_ASSERT(thr != NULL);
74119 	DUK_ASSERT(tv_val_unstable != NULL);
74120 
74121 	act = thr->callstack_curr;
74122 	DUK_ASSERT(act != NULL);
74123 	DUK_ASSERT(act->cat != NULL);
74124 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
74125 
74126 	duk__set_catcher_regs_norz(thr, act->cat, tv_val_unstable, lj_type);
74127 
74128 	DUK_ASSERT(thr->callstack_top >= 1);
74129 	DUK_ASSERT(thr->callstack_curr != NULL);
74130 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
74131 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
74132 
74133 	DUK_ASSERT(thr->callstack_top >= 1);
74134 	DUK_ASSERT(act == thr->callstack_curr);
74135 	DUK_ASSERT(act != NULL);
74136 	duk__reconfig_valstack_ecma_catcher(thr, act);
74137 
74138 	DUK_ASSERT(thr->callstack_top >= 1);
74139 	DUK_ASSERT(act == thr->callstack_curr);
74140 	DUK_ASSERT(act != NULL);
74141 	cat = act->cat;
74142 	DUK_ASSERT(cat != NULL);
74143 
74144 	act->curr_pc = cat->pc_base + 1;  /* +1 = finally */
74145 
74146 	DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
74147 }
74148 
74149 DUK_LOCAL void duk__handle_label(duk_hthread *thr, duk_small_uint_t lj_type) {
74150 	duk_activation *act;
74151 	duk_catcher *cat;
74152 
74153 	DUK_ASSERT(thr != NULL);
74154 
74155 	DUK_ASSERT(thr->callstack_top >= 1);
74156 	act = thr->callstack_curr;
74157 	DUK_ASSERT(act != NULL);
74158 	DUK_ASSERT(DUK_ACT_GET_FUNC(act) != NULL);
74159 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(DUK_ACT_GET_FUNC(act)));
74160 
74161 	/* +0 = break, +1 = continue */
74162 	cat = act->cat;
74163 	DUK_ASSERT(cat != NULL);
74164 	DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL);
74165 
74166 	act->curr_pc = cat->pc_base + (lj_type == DUK_LJ_TYPE_CONTINUE ? 1 : 0);
74167 
74168 	/* valstack should not need changes */
74169 #if defined(DUK_USE_ASSERTIONS)
74170 	DUK_ASSERT(thr->callstack_top >= 1);
74171 	DUK_ASSERT(act == thr->callstack_curr);
74172 	DUK_ASSERT(act != NULL);
74173 	DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack_bottom) ==
74174 	           (duk_size_t) ((duk_hcompfunc *) DUK_ACT_GET_FUNC(act))->nregs);
74175 #endif
74176 }
74177 
74178 /* Called for handling both a longjmp() with type DUK_LJ_TYPE_YIELD and
74179  * when a RETURN opcode terminates a thread and yields to the resumer.
74180  * Caller unwinds so that top of callstack is the activation we return to.
74181  */
74182 #if defined(DUK_USE_COROUTINE_SUPPORT)
74183 DUK_LOCAL void duk__handle_yield(duk_hthread *thr, duk_hthread *resumer, duk_tval *tv_val_unstable) {
74184 	duk_activation *act_resumer;
74185 	duk_tval *tv1;
74186 
74187 	DUK_ASSERT(thr != NULL);
74188 	DUK_ASSERT(resumer != NULL);
74189 	DUK_ASSERT(tv_val_unstable != NULL);
74190 	act_resumer = resumer->callstack_curr;
74191 	DUK_ASSERT(act_resumer != NULL);
74192 	DUK_ASSERT(DUK_ACT_GET_FUNC(act_resumer) != NULL);
74193 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(act_resumer)));  /* resume caller must be an ECMAScript func */
74194 
74195 	tv1 = (duk_tval *) (void *) ((duk_uint8_t *) resumer->valstack + act_resumer->retval_byteoff);  /* return value from Duktape.Thread.resume() */
74196 	DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv_val_unstable);  /* side effects */  /* XXX: avoid side effects */
74197 
74198 	duk__reconfig_valstack_ecma_return(resumer);
74199 
74200 	/* caller must change active thread, and set thr->resumer to NULL */
74201 }
74202 #endif  /* DUK_USE_COROUTINE_SUPPORT */
74203 
74204 DUK_LOCAL duk_small_uint_t duk__handle_longjmp(duk_hthread *thr, duk_activation *entry_act) {
74205 	duk_small_uint_t retval = DUK__LONGJMP_RESTART;
74206 
74207 	DUK_ASSERT(thr != NULL);
74208 	DUK_ASSERT(entry_act != NULL);
74209 
74210 	/* 'thr' is the current thread, as no-one resumes except us and we
74211 	 * switch 'thr' in that case.
74212 	 */
74213 	DUK_ASSERT(thr == thr->heap->curr_thread);
74214 
74215 	/*
74216 	 *  (Re)try handling the longjmp.
74217 	 *
74218 	 *  A longjmp handler may convert the longjmp to a different type and
74219 	 *  "virtually" rethrow by goto'ing to 'check_longjmp'.  Before the goto,
74220 	 *  the following must be updated:
74221 	 *    - the heap 'lj' state
74222 	 *    - 'thr' must reflect the "throwing" thread
74223 	 */
74224 
74225  check_longjmp:
74226 
74227 	DUK_DD(DUK_DDPRINT("handling longjmp: type=%ld, value1=%!T, value2=%!T, iserror=%ld",
74228 	                   (long) thr->heap->lj.type,
74229 	                   (duk_tval *) &thr->heap->lj.value1,
74230 	                   (duk_tval *) &thr->heap->lj.value2,
74231 	                   (long) thr->heap->lj.iserror));
74232 
74233 	switch (thr->heap->lj.type) {
74234 
74235 #if defined(DUK_USE_COROUTINE_SUPPORT)
74236 	case DUK_LJ_TYPE_RESUME: {
74237 		/*
74238 		 *  Note: lj.value1 is 'value', lj.value2 is 'resumee'.
74239 		 *  This differs from YIELD.
74240 		 */
74241 
74242 		duk_tval *tv;
74243 		duk_tval *tv2;
74244 		duk_hthread *resumee;
74245 
74246 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
74247 
74248 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged by Duktape.Thread.resume() */
74249 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.resume() activation */
74250 		DUK_ASSERT(thr->callstack_curr != NULL);
74251 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74252 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
74253 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
74254 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_resume);
74255 
74256 		tv = &thr->heap->lj.value2;  /* resumee */
74257 		DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
74258 		DUK_ASSERT(DUK_TVAL_GET_OBJECT(tv) != NULL);
74259 		DUK_ASSERT(DUK_HOBJECT_IS_THREAD(DUK_TVAL_GET_OBJECT(tv)));
74260 		resumee = (duk_hthread *) DUK_TVAL_GET_OBJECT(tv);
74261 
74262 		DUK_ASSERT(resumee != NULL);
74263 		DUK_ASSERT(resumee->resumer == NULL);
74264 		DUK_ASSERT(resumee->state == DUK_HTHREAD_STATE_INACTIVE ||
74265 		           resumee->state == DUK_HTHREAD_STATE_YIELDED);                                                     /* checked by Duktape.Thread.resume() */
74266 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74267 		           resumee->callstack_top >= 2);                                                                     /* YIELDED: ECMAScript activation + Duktape.Thread.yield() activation */
74268 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_YIELDED ||
74269 		           (DUK_ACT_GET_FUNC(resumee->callstack_curr) != NULL &&
74270 		            DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumee->callstack_curr)) &&
74271 		            ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumee->callstack_curr))->func == duk_bi_thread_yield));
74272 		DUK_ASSERT(resumee->state != DUK_HTHREAD_STATE_INACTIVE ||
74273 		           resumee->callstack_top == 0);                                                                     /* INACTIVE: no activation, single function value on valstack */
74274 
74275 		if (thr->heap->lj.iserror) {
74276 			/*
74277 			 *  Throw the error in the resumed thread's context; the
74278 			 *  error value is pushed onto the resumee valstack.
74279 			 *
74280 			 *  Note: the callstack of the target may empty in this case
74281 			 *  too (i.e. the target thread has never been resumed).  The
74282 			 *  value stack will contain the initial function in that case,
74283 			 *  which we simply ignore.
74284 			 */
74285 
74286 			DUK_ASSERT(resumee->resumer == NULL);
74287 			resumee->resumer = thr;
74288 			DUK_HTHREAD_INCREF(thr, thr);
74289 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74290 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74291 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74292 			thr = resumee;
74293 
74294 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
74295 
74296 			/* thr->heap->lj.value1 is already the value to throw */
74297 			/* thr->heap->lj.value2 is 'thread', will be wiped out at the end */
74298 
74299 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
74300 
74301 			DUK_DD(DUK_DDPRINT("-> resume with an error, converted to a throw in the resumee, propagate"));
74302 			goto check_longjmp;
74303 		} else if (resumee->state == DUK_HTHREAD_STATE_YIELDED) {
74304 			/* Unwind previous Duktape.Thread.yield() call.  The
74305 			 * activation remaining must always be an ECMAScript
74306 			 * call now (yield() accepts calls from ECMAScript
74307 			 * only).
74308 			 */
74309 			duk_activation *act_resumee;
74310 
74311 			DUK_ASSERT(resumee->callstack_top >= 2);
74312 			act_resumee = resumee->callstack_curr;  /* Duktape.Thread.yield() */
74313 			DUK_ASSERT(act_resumee != NULL);
74314 			act_resumee = act_resumee->parent;      /* ECMAScript call site for yield() */
74315 			DUK_ASSERT(act_resumee != NULL);
74316 
74317 			tv = (duk_tval *) (void *) ((duk_uint8_t *) resumee->valstack + act_resumee->retval_byteoff);  /* return value from Duktape.Thread.yield() */
74318 			DUK_ASSERT(tv >= resumee->valstack && tv < resumee->valstack_top);
74319 			tv2 = &thr->heap->lj.value1;
74320 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv, tv2);  /* side effects */  /* XXX: avoid side effects */
74321 
74322 			duk_hthread_activation_unwind_norz(resumee);  /* unwind to 'yield' caller */
74323 			/* no need to unwind catch stack */
74324 
74325 			duk__reconfig_valstack_ecma_return(resumee);
74326 
74327 			DUK_ASSERT(resumee->resumer == NULL);
74328 			resumee->resumer = thr;
74329 			DUK_HTHREAD_INCREF(thr, thr);
74330 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74331 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74332 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74333 #if 0
74334 			thr = resumee;  /* not needed, as we exit right away */
74335 #endif
74336 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
74337 			retval = DUK__LONGJMP_RESTART;
74338 			goto wipe_and_return;
74339 		} else {
74340 			/* Initial resume call. */
74341 			duk_small_uint_t call_flags;
74342 			duk_int_t setup_rc;
74343 
74344 			/* resumee: [... initial_func]  (currently actually: [initial_func]) */
74345 
74346 			duk_push_undefined(resumee);
74347 			tv = &thr->heap->lj.value1;
74348 			duk_push_tval(resumee, tv);
74349 
74350 			/* resumee: [... initial_func undefined(= this) resume_value ] */
74351 
74352 			call_flags = DUK_CALL_FLAG_ALLOW_ECMATOECMA;  /* not tailcall, ecma-to-ecma (assumed to succeed) */
74353 
74354 			setup_rc = duk_handle_call_unprotected_nargs(resumee, 1 /*nargs*/, call_flags);
74355 			if (setup_rc == 0) {
74356 				/* This shouldn't happen; Duktape.Thread.resume()
74357 				 * should make sure of that.  If it does happen
74358 				 * this internal error will propagate out of the
74359 				 * executor which can be quite misleading.
74360 				 */
74361 				DUK_ERROR_INTERNAL(thr);
74362 				DUK_WO_NORETURN(return 0;);
74363 			}
74364 
74365 			DUK_ASSERT(resumee->resumer == NULL);
74366 			resumee->resumer = thr;
74367 			DUK_HTHREAD_INCREF(thr, thr);
74368 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
74369 			thr->state = DUK_HTHREAD_STATE_RESUMED;
74370 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
74371 #if 0
74372 			thr = resumee;  /* not needed, as we exit right away */
74373 #endif
74374 			DUK_DD(DUK_DDPRINT("-> resume with a value, restart execution in resumee"));
74375 			retval = DUK__LONGJMP_RESTART;
74376 			goto wipe_and_return;
74377 		}
74378 		DUK_UNREACHABLE();
74379 		break;  /* never here */
74380 	}
74381 
74382 	case DUK_LJ_TYPE_YIELD: {
74383 		/*
74384 		 *  Currently only allowed only if yielding thread has only
74385 		 *  ECMAScript activations (except for the Duktape.Thread.yield()
74386 		 *  call at the callstack top) and none of them constructor
74387 		 *  calls.
74388 		 *
74389 		 *  This excludes the 'entry' thread which will always have
74390 		 *  a preventcount > 0.
74391 		 */
74392 
74393 		duk_hthread *resumer;
74394 
74395 		/* duk_bi_duk_object_yield() and duk_bi_duk_object_resume() ensure all of these are met */
74396 
74397 #if 0  /* entry_thread not available for assert */
74398 		DUK_ASSERT(thr != entry_thread);                                                                             /* Duktape.Thread.yield() should prevent */
74399 #endif
74400 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);                                                         /* unchanged from Duktape.Thread.yield() */
74401 		DUK_ASSERT(thr->callstack_top >= 2);                                                                         /* ECMAScript activation + Duktape.Thread.yield() activation */
74402 		DUK_ASSERT(thr->callstack_curr != NULL);
74403 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74404 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL &&
74405 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)) &&
74406 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->callstack_curr))->func == duk_bi_thread_yield);
74407 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr->parent) != NULL &&
74408 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));                              /* an ECMAScript function */
74409 
74410 		resumer = thr->resumer;
74411 
74412 		DUK_ASSERT(resumer != NULL);
74413 		DUK_ASSERT(resumer->state == DUK_HTHREAD_STATE_RESUMED);                                                     /* written by a previous RESUME handling */
74414 		DUK_ASSERT(resumer->callstack_top >= 2);                                                                     /* ECMAScript activation + Duktape.Thread.resume() activation */
74415 		DUK_ASSERT(resumer->callstack_curr != NULL);
74416 		DUK_ASSERT(resumer->callstack_curr->parent != NULL);
74417 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr) != NULL &&
74418 		           DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr)) &&
74419 		           ((duk_hnatfunc *) DUK_ACT_GET_FUNC(resumer->callstack_curr))->func == duk_bi_thread_resume);
74420 		DUK_ASSERT(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent) != NULL &&
74421 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(resumer->callstack_curr->parent)));                            /* an ECMAScript function */
74422 
74423 		if (thr->heap->lj.iserror) {
74424 			thr->state = DUK_HTHREAD_STATE_YIELDED;
74425 			thr->resumer = NULL;
74426 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74427 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
74428 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74429 			thr = resumer;
74430 
74431 			thr->heap->lj.type = DUK_LJ_TYPE_THROW;
74432 			/* lj.value1 is already set */
74433 			DUK_ASSERT(thr->heap->lj.iserror);  /* already set */
74434 
74435 			DUK_DD(DUK_DDPRINT("-> yield an error, converted to a throw in the resumer, propagate"));
74436 			goto check_longjmp;
74437 		} else {
74438 			duk_hthread_activation_unwind_norz(resumer);
74439 			duk__handle_yield(thr, resumer, &thr->heap->lj.value1);
74440 
74441 			thr->state = DUK_HTHREAD_STATE_YIELDED;
74442 			thr->resumer = NULL;
74443 			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74444 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
74445 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74446 #if 0
74447 			thr = resumer;  /* not needed, as we exit right away */
74448 #endif
74449 
74450 			DUK_DD(DUK_DDPRINT("-> yield a value, restart execution in resumer"));
74451 			retval = DUK__LONGJMP_RESTART;
74452 			goto wipe_and_return;
74453 		}
74454 		DUK_UNREACHABLE();
74455 		break;  /* never here */
74456 	}
74457 #endif  /* DUK_USE_COROUTINE_SUPPORT */
74458 
74459 	case DUK_LJ_TYPE_THROW: {
74460 		/*
74461 		 *  Three possible outcomes:
74462 		 *    * A try or finally catcher is found => resume there.
74463 		 *      (or)
74464 		 *    * The error propagates to the bytecode executor entry
74465 		 *      level (and we're in the entry thread) => rethrow
74466 		 *      with a new longjmp(), after restoring the previous
74467 		 *      catchpoint.
74468 		 *    * The error is not caught in the current thread, so
74469 		 *      the thread finishes with an error.  This works like
74470 		 *      a yielded error, except that the thread is finished
74471 		 *      and can no longer be resumed.  (There is always a
74472 		 *      resumer in this case.)
74473 		 *
74474 		 *  Note: until we hit the entry level, there can only be
74475 		 *  ECMAScript activations.
74476 		 */
74477 
74478 		duk_activation *act;
74479 		duk_catcher *cat;
74480 		duk_hthread *resumer;
74481 
74482 		for (;;) {
74483 			act = thr->callstack_curr;
74484 			if (act == NULL) {
74485 				break;
74486 			}
74487 
74488 			for (;;) {
74489 				cat = act->cat;
74490 				if (cat == NULL) {
74491 					break;
74492 				}
74493 
74494 				if (DUK_CAT_HAS_CATCH_ENABLED(cat)) {
74495 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
74496 
74497 					duk__handle_catch(thr,
74498 					                  &thr->heap->lj.value1,
74499 					                  DUK_LJ_TYPE_THROW);
74500 
74501 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'catch' clause, restart execution"));
74502 					retval = DUK__LONGJMP_RESTART;
74503 					goto wipe_and_return;
74504 				}
74505 
74506 				if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74507 					DUK_ASSERT(DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF);
74508 					DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));
74509 
74510 					duk__handle_finally(thr,
74511 					                    &thr->heap->lj.value1,
74512 					                    DUK_LJ_TYPE_THROW);
74513 
74514 					DUK_DD(DUK_DDPRINT("-> throw caught by a 'finally' clause, restart execution"));
74515 					retval = DUK__LONGJMP_RESTART;
74516 					goto wipe_and_return;
74517 				}
74518 
74519 				duk_hthread_catcher_unwind_norz(thr, act);
74520 			}
74521 
74522 			if (act == entry_act) {
74523 				/* Not caught by anything before entry level; rethrow and let the
74524 				 * final catcher finish unwinding (esp. value stack).
74525 				 */
74526 				DUK_D(DUK_DPRINT("-> throw propagated up to entry level, rethrow and exit bytecode executor"));
74527 				retval = DUK__LONGJMP_RETHROW;
74528 				goto just_return;
74529 			}
74530 
74531 			duk_hthread_activation_unwind_norz(thr);
74532 		}
74533 
74534 		DUK_DD(DUK_DDPRINT("-> throw not caught by current thread, yield error to resumer and recheck longjmp"));
74535 
74536 		/* Not caught by current thread, thread terminates (yield error to resumer);
74537 		 * note that this may cause a cascade if the resumer terminates with an uncaught
74538 		 * exception etc (this is OK, but needs careful testing).
74539 		 */
74540 
74541 		DUK_ASSERT(thr->resumer != NULL);
74542 		DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
74543 		DUK_ASSERT(thr->resumer->callstack_curr != NULL);
74544 		DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
74545 		DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
74546 		           DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
74547 
74548 		resumer = thr->resumer;
74549 
74550 		/* reset longjmp */
74551 
74552 		DUK_ASSERT(thr->heap->lj.type == DUK_LJ_TYPE_THROW);  /* already set */
74553 		/* lj.value1 already set */
74554 
74555 		duk_hthread_terminate(thr);  /* updates thread state, minimizes its allocations */
74556 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
74557 
74558 		thr->resumer = NULL;
74559 		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
74560 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
74561 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74562 		thr = resumer;
74563 		goto check_longjmp;
74564 	}
74565 
74566 	case DUK_LJ_TYPE_BREAK:  /* pseudotypes, not used in actual longjmps */
74567 	case DUK_LJ_TYPE_CONTINUE:
74568 	case DUK_LJ_TYPE_RETURN:
74569 	case DUK_LJ_TYPE_NORMAL:
74570 	default: {
74571 		/* should never happen, but be robust */
74572 		DUK_D(DUK_DPRINT("caught unknown longjmp type %ld, treat as internal error", (long) thr->heap->lj.type));
74573 		goto convert_to_internal_error;
74574 	}
74575 
74576 	}  /* end switch */
74577 
74578 	DUK_UNREACHABLE();
74579 
74580  wipe_and_return:
74581 	/* this is not strictly necessary, but helps debugging */
74582 	thr->heap->lj.type = DUK_LJ_TYPE_UNKNOWN;
74583 	thr->heap->lj.iserror = 0;
74584 
74585 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value1);  /* side effects */
74586 	DUK_TVAL_SET_UNDEFINED_UPDREF(thr, &thr->heap->lj.value2);  /* side effects */
74587 
74588 	DUK_GC_TORTURE(thr->heap);
74589 
74590  just_return:
74591 	return retval;
74592 
74593  convert_to_internal_error:
74594 	/* This could also be thrown internally (set the error, goto check_longjmp),
74595 	 * but it's better for internal errors to bubble outwards so that we won't
74596 	 * infinite loop in this catchpoint.
74597 	 */
74598 	DUK_ERROR_INTERNAL(thr);
74599 	DUK_WO_NORETURN(return 0;);
74600 }
74601 
74602 /* Handle a BREAK/CONTINUE opcode.  Avoid using longjmp() for BREAK/CONTINUE
74603  * handling because it has a measurable performance impact in ordinary
74604  * environments and an extreme impact in Emscripten (GH-342).
74605  */
74606 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_break_or_continue(duk_hthread *thr,
74607                                                                 duk_uint_t label_id,
74608                                                                 duk_small_uint_t lj_type) {
74609 	duk_activation *act;
74610 	duk_catcher *cat;
74611 
74612 	DUK_ASSERT(thr != NULL);
74613 
74614 	/* Find a matching label catcher or 'finally' catcher in
74615 	 * the same function, unwinding catchers as we go.
74616 	 *
74617 	 * A label catcher must always exist and will match unless
74618 	 * a 'finally' captures the break/continue first.  It is the
74619 	 * compiler's responsibility to ensure that labels are used
74620 	 * correctly.
74621 	 */
74622 
74623 	act = thr->callstack_curr;
74624 	DUK_ASSERT(act != NULL);
74625 
74626 	for (;;) {
74627 		cat = act->cat;
74628 		if (cat == NULL) {
74629 			break;
74630 		}
74631 
74632 		DUK_DDD(DUK_DDDPRINT("considering catcher %p: type=%ld label=%ld",
74633 		                     (void *) cat,
74634 		                     (long) DUK_CAT_GET_TYPE(cat),
74635 		                     (long) DUK_CAT_GET_LABEL(cat)));
74636 
74637 		/* XXX: bit mask test; FINALLY <-> TCF, single bit mask would suffice? */
74638 
74639 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
74640 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74641 			duk_tval tv_tmp;
74642 
74643 			DUK_TVAL_SET_U32(&tv_tmp, (duk_uint32_t) label_id);
74644 			duk__handle_finally(thr, &tv_tmp, lj_type);
74645 
74646 			DUK_DD(DUK_DDPRINT("-> break/continue caught by 'finally', restart execution"));
74647 			return;
74648 		}
74649 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_LABEL &&
74650 		    (duk_uint_t) DUK_CAT_GET_LABEL(cat) == label_id) {
74651 			duk__handle_label(thr, lj_type);
74652 
74653 			DUK_DD(DUK_DDPRINT("-> break/continue caught by a label catcher (in the same function), restart execution"));
74654 			return;
74655 		}
74656 
74657 		duk_hthread_catcher_unwind_norz(thr, act);
74658 	}
74659 
74660 	/* Should never happen, but be robust. */
74661 	DUK_D(DUK_DPRINT("-> break/continue not caught by anything in the current function (should never happen), throw internal error"));
74662 	DUK_ERROR_INTERNAL(thr);
74663 	DUK_WO_NORETURN(return;);
74664 }
74665 
74666 /* Handle a RETURN opcode.  Avoid using longjmp() for return handling because
74667  * it has a measurable performance impact in ordinary environments and an extreme
74668  * impact in Emscripten (GH-342).  Return value is on value stack top.
74669  */
74670 DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr, duk_activation *entry_act) {
74671 	duk_tval *tv1;
74672 	duk_tval *tv2;
74673 #if defined(DUK_USE_COROUTINE_SUPPORT)
74674 	duk_hthread *resumer;
74675 #endif
74676 	duk_activation *act;
74677 	duk_catcher *cat;
74678 
74679 	/* We can directly access value stack here. */
74680 
74681 	DUK_ASSERT(thr != NULL);
74682 	DUK_ASSERT(entry_act != NULL);
74683 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74684 	tv1 = thr->valstack_top - 1;
74685 	DUK_TVAL_CHKFAST_INPLACE_FAST(tv1);  /* fastint downgrade check for return values */
74686 
74687 	/*
74688 	 *  Four possible outcomes:
74689 	 *
74690 	 *    1. A 'finally' in the same function catches the 'return'.
74691 	 *       It may continue to propagate when 'finally' is finished,
74692 	 *       or it may be neutralized by 'finally' (both handled by
74693 	 *       ENDFIN).
74694 	 *
74695 	 *    2. The return happens at the entry level of the bytecode
74696 	 *       executor, so return from the executor (in C stack).
74697 	 *
74698 	 *    3. There is a calling (ECMAScript) activation in the call
74699 	 *       stack => return to it, in the same executor instance.
74700 	 *
74701 	 *    4. There is no calling activation, and the thread is
74702 	 *       terminated.  There is always a resumer in this case,
74703 	 *       which gets the return value similarly to a 'yield'
74704 	 *       (except that the current thread can no longer be
74705 	 *       resumed).
74706 	 */
74707 
74708 	DUK_ASSERT(thr != NULL);
74709 	DUK_ASSERT(thr->callstack_top >= 1);
74710 
74711 	act = thr->callstack_curr;
74712 	DUK_ASSERT(act != NULL);
74713 
74714 	for (;;) {
74715 		cat = act->cat;
74716 		if (cat == NULL) {
74717 			break;
74718 		}
74719 
74720 		if (DUK_CAT_GET_TYPE(cat) == DUK_CAT_TYPE_TCF &&
74721 		    DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
74722 			DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74723 			duk__handle_finally(thr, thr->valstack_top - 1, DUK_LJ_TYPE_RETURN);
74724 
74725 			DUK_DD(DUK_DDPRINT("-> return caught by 'finally', restart execution"));
74726 			return DUK__RETHAND_RESTART;
74727 		}
74728 
74729 		duk_hthread_catcher_unwind_norz(thr, act);
74730 	}
74731 
74732 	if (act == entry_act) {
74733 		/* Return to the bytecode executor caller who will unwind stacks
74734 		 * and handle constructor post-processing.
74735 		 * Return value is already on the stack top: [ ... retval ].
74736 		 */
74737 
74738 		DUK_DDD(DUK_DDDPRINT("-> return propagated up to entry level, exit bytecode executor"));
74739 		return DUK__RETHAND_FINISHED;
74740 	}
74741 
74742 	if (thr->callstack_top >= 2) {
74743 		/* There is a caller; it MUST be an ECMAScript caller (otherwise it would
74744 		 * match entry_act check).
74745 		 */
74746 		DUK_DDD(DUK_DDDPRINT("return to ECMAScript caller, retval_byteoff=%ld, lj_value1=%!T",
74747 		                     (long) (thr->callstack_curr->parent->retval_byteoff),
74748 		                     (duk_tval *) &thr->heap->lj.value1));
74749 
74750 		DUK_ASSERT(thr->callstack_curr != NULL);
74751 		DUK_ASSERT(thr->callstack_curr->parent != NULL);
74752 		DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr->parent)));   /* must be ECMAScript */
74753 
74754 #if defined(DUK_USE_ES6_PROXY)
74755 		if (thr->callstack_curr->flags & (DUK_ACT_FLAG_CONSTRUCT | DUK_ACT_FLAG_CONSTRUCT_PROXY)) {
74756 			duk_call_construct_postprocess(thr, thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT_PROXY);  /* side effects */
74757 		}
74758 #else
74759 		if (thr->callstack_curr->flags & DUK_ACT_FLAG_CONSTRUCT) {
74760 			duk_call_construct_postprocess(thr, 0);  /* side effects */
74761 		}
74762 #endif
74763 
74764 		tv1 = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + thr->callstack_curr->parent->retval_byteoff);
74765 		DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74766 		tv2 = thr->valstack_top - 1;
74767 		DUK_TVAL_SET_TVAL_UPDREF(thr, tv1, tv2);  /* side effects */
74768 
74769 		/* Catch stack unwind happens inline in callstack unwind. */
74770 		duk_hthread_activation_unwind_norz(thr);
74771 
74772 		duk__reconfig_valstack_ecma_return(thr);
74773 
74774 		DUK_DD(DUK_DDPRINT("-> return not intercepted, restart execution in caller"));
74775 		return DUK__RETHAND_RESTART;
74776 	}
74777 
74778 #if defined(DUK_USE_COROUTINE_SUPPORT)
74779 	DUK_DD(DUK_DDPRINT("no calling activation, thread finishes (similar to yield)"));
74780 
74781 	DUK_ASSERT(thr->resumer != NULL);
74782 	DUK_ASSERT(thr->resumer->callstack_top >= 2);  /* ECMAScript activation + Duktape.Thread.resume() activation */
74783 	DUK_ASSERT(thr->resumer->callstack_curr != NULL);
74784 	DUK_ASSERT(thr->resumer->callstack_curr->parent != NULL);
74785 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr) != NULL &&
74786 			DUK_HOBJECT_IS_NATFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr)) &&
74787 			((duk_hnatfunc *) DUK_ACT_GET_FUNC(thr->resumer->callstack_curr))->func == duk_bi_thread_resume);  /* Duktape.Thread.resume() */
74788 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent) != NULL &&
74789 			DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->resumer->callstack_curr->parent)));  /* an ECMAScript function */
74790 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_RUNNING);
74791 	DUK_ASSERT(thr->resumer->state == DUK_HTHREAD_STATE_RESUMED);
74792 
74793 	resumer = thr->resumer;
74794 
74795 	/* Share yield longjmp handler.
74796 	 *
74797 	 * This sequence of steps is a bit fragile (see GH-1845):
74798 	 * - We need the return value from 'thr' (resumed thread) value stack.
74799 	 *   The termination unwinds its value stack, losing the value.
74800 	 * - We need a refcounted reference for 'thr', which may only exist
74801 	 *   in the caller value stack.  We can't unwind or reconfigure the
74802 	 *   caller's value stack without potentially freeing 'thr'.
74803 	 *
74804 	 * Current approach is to capture the 'thr' return value and store
74805 	 * a reference to 'thr' in the caller value stack temporarily.  This
74806 	 * keeps 'thr' reachable until final yield/return handling which
74807 	 * removes the references atomatically.
74808 	 */
74809 
74810 	DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
74811 	duk_hthread_activation_unwind_norz(resumer);  /* May remove last reference to 'thr', but is NORZ. */
74812 	duk_push_tval(resumer, thr->valstack_top - 1);  /* Capture return value, side effect free. */
74813 	duk_push_hthread(resumer, thr);  /* Make 'thr' reachable again, before side effects. */
74814 
74815 	duk_hthread_terminate(thr);  /* Updates thread state, minimizes its allocations. */
74816 	thr->resumer = NULL;
74817 	DUK_HTHREAD_DECREF(thr, resumer);
74818 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
74819 
74820 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
74821 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
74822 
74823 	DUK_ASSERT(resumer->valstack_top - 2 >= resumer->valstack_bottom);
74824 	duk__handle_yield(thr, resumer, resumer->valstack_top - 2);
74825 	thr = NULL;  /* 'thr' invalidated by call */
74826 
74827 #if 0
74828 	thr = resumer;  /* not needed */
74829 #endif
74830 
74831 	DUK_DD(DUK_DDPRINT("-> return not caught, thread terminated; handle like yield, restart execution in resumer"));
74832 	return DUK__RETHAND_RESTART;
74833 #else
74834 	/* Without coroutine support this case should never happen. */
74835 	DUK_ERROR_INTERNAL(thr);
74836 	DUK_WO_NORETURN(return 0;);
74837 #endif
74838 }
74839 
74840 /*
74841  *  Executor interrupt handling
74842  *
74843  *  The handler is called whenever the interrupt countdown reaches zero
74844  *  (or below).  The handler must perform whatever checks are activated,
74845  *  e.g. check for cumulative step count to impose an execution step
74846  *  limit or check for breakpoints or other debugger interaction.
74847  *
74848  *  When the actions are done, the handler must reinit the interrupt
74849  *  init and counter values.  The 'init' value must indicate how many
74850  *  bytecode instructions are executed before the next interrupt.  The
74851  *  counter must interface with the bytecode executor loop.  Concretely,
74852  *  the new init value is normally one higher than the new counter value.
74853  *  For instance, to execute exactly one bytecode instruction the init
74854  *  value is set to 1 and the counter to 0.  If an error is thrown by the
74855  *  interrupt handler, the counters are set to the same value (e.g. both
74856  *  to 0 to cause an interrupt when the next bytecode instruction is about
74857  *  to be executed after error handling).
74858  *
74859  *  Maintaining the init/counter value properly is important for accurate
74860  *  behavior.  For instance, executor step limit needs a cumulative step
74861  *  count which is simply computed as a sum of 'init' values.  This must
74862  *  work accurately even when single stepping.
74863  */
74864 
74865 #if defined(DUK_USE_INTERRUPT_COUNTER)
74866 
74867 #define DUK__INT_NOACTION    0    /* no specific action, resume normal execution */
74868 #define DUK__INT_RESTART     1    /* must "goto restart_execution", e.g. breakpoints changed */
74869 
74870 #if defined(DUK_USE_DEBUGGER_SUPPORT)
74871 DUK_LOCAL void duk__interrupt_handle_debugger(duk_hthread *thr, duk_bool_t *out_immediate, duk_small_uint_t *out_interrupt_retval) {
74872 	duk_activation *act;
74873 	duk_breakpoint *bp;
74874 	duk_breakpoint **bp_active;
74875 	duk_uint_fast32_t line = 0;
74876 	duk_bool_t process_messages;
74877 	duk_bool_t processed_messages = 0;
74878 
74879 	DUK_ASSERT(thr->heap->dbg_processing == 0);  /* don't re-enter e.g. during Eval */
74880 
74881 	act = thr->callstack_curr;
74882 	DUK_ASSERT(act != NULL);
74883 
74884 	/* It might seem that replacing 'thr->heap' with just 'heap' below
74885 	 * might be a good idea, but it increases code size slightly
74886 	 * (probably due to unnecessary spilling) at least on x64.
74887 	 */
74888 
74889 	/*
74890 	 *  Single opcode step check
74891 	 */
74892 
74893 	if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE) {
74894 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by one opcode step"));
74895 		duk_debug_set_paused(thr->heap);
74896 	}
74897 
74898 	/*
74899 	 *  Breakpoint and step state checks
74900 	 */
74901 
74902 	if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
74903 	    (thr->heap->dbg_pause_act == thr->callstack_curr)) {
74904 		line = duk_debug_curr_line(thr);
74905 
74906 		if (act->prev_line != line) {
74907 			/* Stepped?  Step out is handled by callstack unwind. */
74908 			if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
74909 			    (thr->heap->dbg_pause_act == thr->callstack_curr) &&
74910 			    (line != thr->heap->dbg_pause_startline)) {
74911 				DUK_D(DUK_DPRINT("PAUSE TRIGGERED by line change, at line %ld",
74912 				                 (long) line));
74913 				duk_debug_set_paused(thr->heap);
74914 			}
74915 
74916 			/* Check for breakpoints only on line transition.
74917 			 * Breakpoint is triggered when we enter the target
74918 			 * line from a different line, and the previous line
74919 			 * was within the same function.
74920 			 *
74921 			 * This condition is tricky: the condition used to be
74922 			 * that transition to -or across- the breakpoint line
74923 			 * triggered the breakpoint.  This seems intuitively
74924 			 * better because it handles breakpoints on lines with
74925 			 * no emitted opcodes; but this leads to the issue
74926 			 * described in: https://github.com/svaarala/duktape/issues/263.
74927 			 */
74928 			bp_active = thr->heap->dbg_breakpoints_active;
74929 			for (;;) {
74930 				bp = *bp_active++;
74931 				if (bp == NULL) {
74932 					break;
74933 				}
74934 
74935 				DUK_ASSERT(bp->filename != NULL);
74936 				if (act->prev_line != bp->line && line == bp->line) {
74937 					DUK_D(DUK_DPRINT("PAUSE TRIGGERED by breakpoint at %!O:%ld",
74938 					                 (duk_heaphdr *) bp->filename, (long) bp->line));
74939 					duk_debug_set_paused(thr->heap);
74940 				}
74941 			}
74942 		} else {
74943 			;
74944 		}
74945 
74946 		act->prev_line = (duk_uint32_t) line;
74947 	}
74948 
74949 	/*
74950 	 *  Rate limit check for sending status update or peeking into
74951 	 *  the debug transport.  Both can be expensive operations that
74952 	 *  we don't want to do on every opcode.
74953 	 *
74954 	 *  Making sure the interval remains reasonable on a wide variety
74955 	 *  of targets and bytecode is difficult without a timestamp, so
74956 	 *  we use a Date-provided timestamp for the rate limit check.
74957 	 *  But since it's also expensive to get a timestamp, a bytecode
74958 	 *  counter is used to rate limit getting timestamps.
74959 	 */
74960 
74961 	process_messages = 0;
74962 	if (thr->heap->dbg_state_dirty || DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) || thr->heap->dbg_detaching) {
74963 		/* Enter message processing loop for sending Status notifys and
74964 		 * to finish a pending detach.
74965 		 */
74966 		process_messages = 1;
74967 	}
74968 
74969 	/* XXX: remove heap->dbg_exec_counter, use heap->inst_count_interrupt instead? */
74970 	DUK_ASSERT(thr->interrupt_init >= 0);
74971 	thr->heap->dbg_exec_counter += (duk_uint_t) thr->interrupt_init;
74972 	if (thr->heap->dbg_exec_counter - thr->heap->dbg_last_counter >= DUK_HEAP_DBG_RATELIMIT_OPCODES) {
74973 		/* Overflow of the execution counter is fine and doesn't break
74974 		 * anything here.
74975 		 */
74976 
74977 		duk_double_t now, diff_last;
74978 
74979 		thr->heap->dbg_last_counter = thr->heap->dbg_exec_counter;
74980 		now = duk_time_get_monotonic_time(thr);
74981 
74982 		diff_last = now - thr->heap->dbg_last_time;
74983 		if (diff_last < 0.0 || diff_last >= (duk_double_t) DUK_HEAP_DBG_RATELIMIT_MILLISECS) {
74984 			/* Monotonic time should not experience time jumps,
74985 			 * but the provider may be missing and we're actually
74986 			 * using ECMAScript time.  So, tolerate negative values
74987 			 * so that a time jump works reasonably.
74988 			 *
74989 			 * Same interval is now used for status sending and
74990 			 * peeking.
74991 			 */
74992 
74993 			thr->heap->dbg_last_time = now;
74994 			thr->heap->dbg_state_dirty = 1;
74995 			process_messages = 1;
74996 		}
74997 	}
74998 
74999 	/*
75000 	 *  Process messages and send status if necessary.
75001 	 *
75002 	 *  If we're paused, we'll block for new messages.  If we're not
75003 	 *  paused, we'll process anything we can peek but won't block
75004 	 *  for more.  Detach (and re-attach) handling is all localized
75005 	 *  to duk_debug_process_messages() too.
75006 	 *
75007 	 *  Debugger writes outside the message loop may cause debugger
75008 	 *  detach1 phase to run, after which dbg_read_cb == NULL and
75009 	 *  dbg_detaching != 0.  The message loop will finish the detach
75010 	 *  by running detach2 phase, so enter the message loop also when
75011 	 *  detaching.
75012 	 */
75013 
75014 	if (process_messages) {
75015 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75016 		processed_messages = duk_debug_process_messages(thr, 0 /*no_block*/);
75017 		DUK_ASSERT(thr->heap->dbg_processing == 0);
75018 	}
75019 
75020 	/* Continue checked execution if there are breakpoints or we're stepping.
75021 	 * Also use checked execution if paused flag is active - it shouldn't be
75022 	 * because the debug message loop shouldn't terminate if it was.  Step out
75023 	 * is handled by callstack unwind and doesn't need checked execution.
75024 	 * Note that debugger may have detached due to error or explicit request
75025 	 * above, so we must recheck attach status.
75026 	 */
75027 
75028 	if (duk_debug_is_attached(thr->heap)) {
75029 		DUK_ASSERT(act == thr->callstack_curr);
75030 		DUK_ASSERT(act != NULL);
75031 		if (act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE ||
75032 		    (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) ||
75033 		    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75034 		     thr->heap->dbg_pause_act == thr->callstack_curr) ||
75035 		     DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap)) {
75036 			*out_immediate = 1;
75037 		}
75038 
75039 		/* If we processed any debug messages breakpoints may have
75040 		 * changed; restart execution to re-check active breakpoints.
75041 		 */
75042 		if (processed_messages) {
75043 			DUK_D(DUK_DPRINT("processed debug messages, restart execution to recheck possibly changed breakpoints"));
75044 			*out_interrupt_retval = DUK__INT_RESTART;
75045 		} else {
75046 			if (thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_ONE_OPCODE) {
75047 				/* Set 'pause after one opcode' active only when we're
75048 				 * actually just about to execute code.
75049 				 */
75050 				thr->heap->dbg_pause_flags |= DUK_PAUSE_FLAG_ONE_OPCODE_ACTIVE;
75051 			}
75052 		}
75053 	} else {
75054 		DUK_D(DUK_DPRINT("debugger became detached, resume normal execution"));
75055 	}
75056 }
75057 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75058 
75059 DUK_LOCAL DUK__NOINLINE_PERF DUK_COLD duk_small_uint_t duk__executor_interrupt(duk_hthread *thr) {
75060 	duk_int_t ctr;
75061 	duk_activation *act;
75062 	duk_hcompfunc *fun;
75063 	duk_bool_t immediate = 0;
75064 	duk_small_uint_t retval;
75065 
75066 	DUK_ASSERT(thr != NULL);
75067 	DUK_ASSERT(thr->heap != NULL);
75068 	DUK_ASSERT(thr->callstack_top > 0);
75069 
75070 #if defined(DUK_USE_DEBUG)
75071 	thr->heap->inst_count_interrupt += thr->interrupt_init;
75072 	DUK_DD(DUK_DDPRINT("execution interrupt, counter=%ld, init=%ld, "
75073 	                   "instruction counts: executor=%ld, interrupt=%ld",
75074 	                   (long) thr->interrupt_counter, (long) thr->interrupt_init,
75075 	                   (long) thr->heap->inst_count_exec, (long) thr->heap->inst_count_interrupt));
75076 #endif
75077 
75078 	retval = DUK__INT_NOACTION;
75079 	ctr = DUK_HTHREAD_INTCTR_DEFAULT;
75080 
75081 	/*
75082 	 *  Avoid nested calls.  Concretely this happens during debugging, e.g.
75083 	 *  when we eval() an expression.
75084 	 *
75085 	 *  Also don't interrupt if we're currently doing debug processing
75086 	 *  (which can be initiated outside the bytecode executor) as this
75087 	 *  may cause the debugger to be called recursively.  Check required
75088 	 *  for correct operation of throw intercept and other "exotic" halting
75089 	 * scenarios.
75090 	 */
75091 
75092 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75093 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap) || thr->heap->dbg_processing) {
75094 #else
75095 	if (DUK_HEAP_HAS_INTERRUPT_RUNNING(thr->heap)) {
75096 #endif
75097 		DUK_DD(DUK_DDPRINT("nested executor interrupt, ignoring"));
75098 
75099 		/* Set a high interrupt counter; the original executor
75100 		 * interrupt invocation will rewrite before exiting.
75101 		 */
75102 		thr->interrupt_init = ctr;
75103 		thr->interrupt_counter = ctr - 1;
75104 		return DUK__INT_NOACTION;
75105 	}
75106 	DUK_HEAP_SET_INTERRUPT_RUNNING(thr->heap);
75107 
75108 	act = thr->callstack_curr;
75109 	DUK_ASSERT(act != NULL);
75110 
75111 	fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
75112 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC((duk_hobject *) fun));
75113 
75114 	DUK_UNREF(fun);
75115 
75116 #if defined(DUK_USE_EXEC_TIMEOUT_CHECK)
75117 	/*
75118 	 *  Execution timeout check
75119 	 */
75120 
75121 	if (DUK_USE_EXEC_TIMEOUT_CHECK(thr->heap->heap_udata)) {
75122 		/* Keep throwing an error whenever we get here.  The unusual values
75123 		 * are set this way because no instruction is ever executed, we just
75124 		 * throw an error until all try/catch/finally and other catchpoints
75125 		 * have been exhausted.  Duktape/C code gets control at each protected
75126 		 * call but whenever it enters back into Duktape the RangeError gets
75127 		 * raised.  User exec timeout check must consistently indicate a timeout
75128 		 * until we've fully bubbled out of Duktape.
75129 		 */
75130 		DUK_D(DUK_DPRINT("execution timeout, throwing a RangeError"));
75131 		thr->interrupt_init = 0;
75132 		thr->interrupt_counter = 0;
75133 		DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75134 		DUK_ERROR_RANGE(thr, "execution timeout");
75135 		DUK_WO_NORETURN(return 0;);
75136 	}
75137 #endif  /* DUK_USE_EXEC_TIMEOUT_CHECK */
75138 
75139 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75140 	if (!thr->heap->dbg_processing &&
75141 	    (thr->heap->dbg_read_cb != NULL || thr->heap->dbg_detaching)) {
75142 		/* Avoid recursive re-entry; enter when we're attached or
75143 		 * detaching (to finish off the pending detach).
75144 		 */
75145 		duk__interrupt_handle_debugger(thr, &immediate, &retval);
75146 		DUK_ASSERT(act == thr->callstack_curr);
75147 	}
75148 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75149 
75150 	/*
75151 	 *  Update the interrupt counter
75152 	 */
75153 
75154 	if (immediate) {
75155 		/* Cause an interrupt after executing one instruction. */
75156 		ctr = 1;
75157 	}
75158 
75159 	/* The counter value is one less than the init value: init value should
75160 	 * indicate how many instructions are executed before interrupt.  To
75161 	 * execute 1 instruction (after interrupt handler return), counter must
75162 	 * be 0.
75163 	 */
75164 	DUK_ASSERT(ctr >= 1);
75165 	thr->interrupt_init = ctr;
75166 	thr->interrupt_counter = ctr - 1;
75167 	DUK_HEAP_CLEAR_INTERRUPT_RUNNING(thr->heap);
75168 
75169 	return retval;
75170 }
75171 #endif  /* DUK_USE_INTERRUPT_COUNTER */
75172 
75173 /*
75174  *  Debugger handling for executor restart
75175  *
75176  *  Check for breakpoints, stepping, etc, and figure out if we should execute
75177  *  in checked or normal mode.  Note that we can't do this when an activation
75178  *  is created, because breakpoint status (and stepping status) may change
75179  *  later, so we must recheck every time we're executing an activation.
75180  *  This primitive should be side effect free to avoid changes during check.
75181  */
75182 
75183 #if defined(DUK_USE_DEBUGGER_SUPPORT)
75184 DUK_LOCAL void duk__executor_recheck_debugger(duk_hthread *thr, duk_activation *act, duk_hcompfunc *fun) {
75185 	duk_heap *heap;
75186 	duk_tval *tv_tmp;
75187 	duk_hstring *filename;
75188 	duk_small_uint_t bp_idx;
75189 	duk_breakpoint **bp_active;
75190 
75191 	DUK_ASSERT(thr != NULL);
75192 	DUK_ASSERT(act != NULL);
75193 	DUK_ASSERT(fun != NULL);
75194 
75195 	heap = thr->heap;
75196 	bp_active = heap->dbg_breakpoints_active;
75197 	act->flags &= ~DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75198 
75199 	tv_tmp = duk_hobject_find_existing_entry_tval_ptr(thr->heap, (duk_hobject *) fun, DUK_HTHREAD_STRING_FILE_NAME(thr));
75200 	if (tv_tmp && DUK_TVAL_IS_STRING(tv_tmp)) {
75201 		filename = DUK_TVAL_GET_STRING(tv_tmp);
75202 
75203 		/* Figure out all active breakpoints.  A breakpoint is
75204 		 * considered active if the current function's fileName
75205 		 * matches the breakpoint's fileName, AND there is no
75206 		 * inner function that has matching line numbers
75207 		 * (otherwise a breakpoint would be triggered both
75208 		 * inside and outside of the inner function which would
75209 		 * be confusing).  Example:
75210 		 *
75211 		 *     function foo() {
75212 		 *         print('foo');
75213 		 *         function bar() {    <-.  breakpoints in these
75214 		 *             print('bar');     |  lines should not affect
75215 		 *         }                   <-'  foo() execution
75216 		 *         bar();
75217 		 *     }
75218 		 *
75219 		 * We need a few things that are only available when
75220 		 * debugger support is enabled: (1) a line range for
75221 		 * each function, and (2) access to the function
75222 		 * template to access the inner functions (and their
75223 		 * line ranges).
75224 		 *
75225 		 * It's important to have a narrow match for active
75226 		 * breakpoints so that we don't enter checked execution
75227 		 * when that's not necessary.  For instance, if we're
75228 		 * running inside a certain function and there's
75229 		 * breakpoint outside in (after the call site), we
75230 		 * don't want to slow down execution of the function.
75231 		 */
75232 
75233 		for (bp_idx = 0; bp_idx < heap->dbg_breakpoint_count; bp_idx++) {
75234 			duk_breakpoint *bp = heap->dbg_breakpoints + bp_idx;
75235 			duk_hobject **funcs, **funcs_end;
75236 			duk_hcompfunc *inner_fun;
75237 			duk_bool_t bp_match;
75238 
75239 			if (bp->filename == filename &&
75240 			    bp->line >= fun->start_line && bp->line <= fun->end_line) {
75241 				bp_match = 1;
75242 				DUK_DD(DUK_DDPRINT("breakpoint filename and line match: "
75243 				                   "%s:%ld vs. %s (line %ld vs. %ld-%ld)",
75244 				                   DUK_HSTRING_GET_DATA(bp->filename),
75245 				                   (long) bp->line,
75246 				                   DUK_HSTRING_GET_DATA(filename),
75247 				                   (long) bp->line,
75248 				                   (long) fun->start_line,
75249 				                   (long) fun->end_line));
75250 
75251 				funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun);
75252 				funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, fun);
75253 				while (funcs != funcs_end) {
75254 					inner_fun = (duk_hcompfunc *) *funcs;
75255 					DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) inner_fun));
75256 					if (bp->line >= inner_fun->start_line && bp->line <= inner_fun->end_line) {
75257 						DUK_DD(DUK_DDPRINT("inner function masks ('captures') breakpoint"));
75258 						bp_match = 0;
75259 						break;
75260 					}
75261 					funcs++;
75262 				}
75263 
75264 				if (bp_match) {
75265 					/* No need to check for size of bp_active list,
75266 					 * it's always larger than maximum number of
75267 					 * breakpoints.
75268 					 */
75269 					act->flags |= DUK_ACT_FLAG_BREAKPOINT_ACTIVE;
75270 					*bp_active = heap->dbg_breakpoints + bp_idx;
75271 					bp_active++;
75272 				}
75273 			}
75274 		}
75275 	}
75276 
75277 	*bp_active = NULL;  /* terminate */
75278 
75279 	DUK_DD(DUK_DDPRINT("ACTIVE BREAKPOINTS: %ld", (long) (bp_active - thr->heap->dbg_breakpoints_active)));
75280 
75281 	/* Force pause if we were doing "step into" in another activation. */
75282 	if ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_FUNC_ENTRY) &&
75283 	    thr->heap->dbg_pause_act != thr->callstack_curr) {
75284 		DUK_D(DUK_DPRINT("PAUSE TRIGGERED by function entry"));
75285 		duk_debug_set_paused(thr->heap);
75286 	}
75287 
75288 	/* Force interrupt right away if we're paused or in "checked mode".
75289 	 * Step out is handled by callstack unwind.
75290 	 */
75291 	if ((act->flags & DUK_ACT_FLAG_BREAKPOINT_ACTIVE) ||
75292 	    DUK_HEAP_HAS_DEBUGGER_PAUSED(thr->heap) ||
75293 	    ((thr->heap->dbg_pause_flags & DUK_PAUSE_FLAG_LINE_CHANGE) &&
75294 	     thr->heap->dbg_pause_act == thr->callstack_curr)) {
75295 		/* We'll need to interrupt early so recompute the init
75296 		 * counter to reflect the number of bytecode instructions
75297 		 * executed so that step counts for e.g. debugger rate
75298 		 * limiting are accurate.
75299 		 */
75300 		DUK_ASSERT(thr->interrupt_counter <= thr->interrupt_init);
75301 		thr->interrupt_init = thr->interrupt_init - thr->interrupt_counter;
75302 		thr->interrupt_counter = 0;
75303 	}
75304 }
75305 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
75306 
75307 /*
75308  *  Opcode handlers for opcodes with a lot of code and which are relatively
75309  *  rare; NOINLINE to reduce amount of code in main bytecode dispatcher.
75310  */
75311 
75312 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initset_initget(duk_hthread *thr, duk_uint_fast32_t ins) {
75313 	duk_bool_t is_set = (DUK_DEC_OP(ins) == DUK_OP_INITSET);
75314 	duk_uint_fast_t idx;
75315 	duk_uint_t defprop_flags;
75316 
75317 	/* A -> object register (acts as a source)
75318 	 * BC -> BC+0 contains key, BC+1 closure (value)
75319 	 */
75320 
75321 	/* INITSET/INITGET are only used to initialize object literal keys.
75322 	 * There may be a previous propery in ES2015 because duplicate property
75323 	 * names are allowed.
75324 	 */
75325 
75326 	/* This could be made more optimal by accessing internals directly. */
75327 
75328 	idx = (duk_uint_fast_t) DUK_DEC_BC(ins);
75329 	duk_dup(thr, (duk_idx_t) (idx + 0));  /* key */
75330 	duk_dup(thr, (duk_idx_t) (idx + 1));  /* getter/setter */
75331 	if (is_set) {
75332 	        defprop_flags = DUK_DEFPROP_HAVE_SETTER |
75333 	                        DUK_DEFPROP_FORCE |
75334 	                        DUK_DEFPROP_SET_ENUMERABLE |
75335 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75336 	} else {
75337 	        defprop_flags = DUK_DEFPROP_HAVE_GETTER |
75338 	                        DUK_DEFPROP_FORCE |
75339 	                        DUK_DEFPROP_SET_ENUMERABLE |
75340 	                        DUK_DEFPROP_SET_CONFIGURABLE;
75341 	}
75342 	duk_def_prop(thr, (duk_idx_t) DUK_DEC_A(ins), defprop_flags);
75343 }
75344 
75345 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_trycatch(duk_hthread *thr, duk_uint_fast32_t ins, duk_instr_t *curr_pc) {
75346 	duk_activation *act;
75347 	duk_catcher *cat;
75348 	duk_tval *tv1;
75349 	duk_small_uint_fast_t a;
75350 	duk_small_uint_fast_t bc;
75351 
75352 	/* A -> flags
75353 	 * BC -> reg_catch; base register for two registers used both during
75354 	 *       trycatch setup and when catch is triggered
75355 	 *
75356 	 *      If DUK_BC_TRYCATCH_FLAG_CATCH_BINDING set:
75357 	 *          reg_catch + 0: catch binding variable name (string).
75358 	 *          Automatic declarative environment is established for
75359 	 *          the duration of the 'catch' clause.
75360 	 *
75361 	 *      If DUK_BC_TRYCATCH_FLAG_WITH_BINDING set:
75362 	 *          reg_catch + 0: with 'target value', which is coerced to
75363 	 *          an object and then used as a bindind object for an
75364 	 *          environment record.  The binding is initialized here, for
75365 	 *          the 'try' clause.
75366 	 *
75367 	 * Note that a TRYCATCH generated for a 'with' statement has no
75368 	 * catch or finally parts.
75369 	 */
75370 
75371 	/* XXX: TRYCATCH handling should be reworked to avoid creating
75372 	 * an explicit scope unless it is actually needed (e.g. function
75373 	 * instances or eval is executed inside the catch block).  This
75374 	 * rework is not trivial because the compiler doesn't have an
75375 	 * intermediate representation.  When the rework is done, the
75376 	 * opcode format can also be made more straightforward.
75377 	 */
75378 
75379 	/* XXX: side effect handling is quite awkward here */
75380 
75381 	DUK_DDD(DUK_DDDPRINT("TRYCATCH: reg_catch=%ld, have_catch=%ld, "
75382 	                     "have_finally=%ld, catch_binding=%ld, with_binding=%ld (flags=0x%02lx)",
75383 	                     (long) DUK_DEC_BC(ins),
75384 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH ? 1 : 0),
75385 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY ? 1 : 0),
75386 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING ? 1 : 0),
75387 	                     (long) (DUK_DEC_A(ins) & DUK_BC_TRYCATCH_FLAG_WITH_BINDING ? 1 : 0),
75388 	                     (unsigned long) DUK_DEC_A(ins)));
75389 
75390 	a = DUK_DEC_A(ins);
75391 	bc = DUK_DEC_BC(ins);
75392 
75393 	/* Registers 'bc' and 'bc + 1' are written in longjmp handling
75394 	 * and if their previous values (which are temporaries) become
75395 	 * unreachable -and- have a finalizer, there'll be a function
75396 	 * call during error handling which is not supported now (GH-287).
75397 	 * Ensure that both 'bc' and 'bc + 1' have primitive values to
75398 	 * guarantee no finalizer calls in error handling.  Scrubbing also
75399 	 * ensures finalizers for the previous values run here rather than
75400 	 * later.  Error handling related values are also written to 'bc'
75401 	 * and 'bc + 1' but those values never become unreachable during
75402 	 * error handling, so there's no side effect problem even if the
75403 	 * error value has a finalizer.
75404 	 */
75405 	duk_dup(thr, (duk_idx_t) bc);  /* Stabilize value. */
75406 	duk_to_undefined(thr, (duk_idx_t) bc);
75407 	duk_to_undefined(thr, (duk_idx_t) (bc + 1));
75408 
75409 	/* Allocate catcher and populate it.  Doesn't have to
75410 	 * be fully atomic, but the catcher must be in a
75411 	 * consistent state if side effects (such as finalizer
75412 	 * calls) occur.
75413 	 */
75414 
75415 	cat = duk_hthread_catcher_alloc(thr);
75416 	DUK_ASSERT(cat != NULL);
75417 
75418 	cat->flags = DUK_CAT_TYPE_TCF;
75419 	cat->h_varname = NULL;
75420 	cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
75421 	cat->idx_base = (duk_size_t) (thr->valstack_bottom - thr->valstack) + bc;
75422 
75423 	act = thr->callstack_curr;
75424 	DUK_ASSERT(act != NULL);
75425 	cat->parent = act->cat;
75426 	act->cat = cat;
75427 
75428 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_CATCH) {
75429 		cat->flags |= DUK_CAT_FLAG_CATCH_ENABLED;
75430 	}
75431 	if (a & DUK_BC_TRYCATCH_FLAG_HAVE_FINALLY) {
75432 		cat->flags |= DUK_CAT_FLAG_FINALLY_ENABLED;
75433 	}
75434 	if (a & DUK_BC_TRYCATCH_FLAG_CATCH_BINDING) {
75435 		DUK_DDD(DUK_DDDPRINT("catch binding flag set to catcher"));
75436 		cat->flags |= DUK_CAT_FLAG_CATCH_BINDING_ENABLED;
75437 		tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
75438 		DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
75439 
75440 		/* borrowed reference; although 'tv1' comes from a register,
75441 		 * its value was loaded using LDCONST so the constant will
75442 		 * also exist and be reachable.
75443 		 */
75444 		cat->h_varname = DUK_TVAL_GET_STRING(tv1);
75445 	} else if (a & DUK_BC_TRYCATCH_FLAG_WITH_BINDING) {
75446 		duk_hobjenv *env;
75447 		duk_hobject *target;
75448 
75449 		/* Delayed env initialization for activation (if needed). */
75450 		DUK_ASSERT(thr->callstack_top >= 1);
75451 		DUK_ASSERT(act == thr->callstack_curr);
75452 		DUK_ASSERT(act != NULL);
75453 		if (act->lex_env == NULL) {
75454 			DUK_DDD(DUK_DDDPRINT("delayed environment initialization"));
75455 			DUK_ASSERT(act->var_env == NULL);
75456 
75457 			duk_js_init_activation_environment_records_delayed(thr, act);
75458 			DUK_ASSERT(act == thr->callstack_curr);
75459 			DUK_UNREF(act);  /* 'act' is no longer accessed, scanbuild fix */
75460 		}
75461 		DUK_ASSERT(act->lex_env != NULL);
75462 		DUK_ASSERT(act->var_env != NULL);
75463 
75464 		/* Coerce 'with' target. */
75465 		target = duk_to_hobject(thr, -1);
75466 		DUK_ASSERT(target != NULL);
75467 
75468 		/* Create an object environment; it is not pushed
75469 		 * so avoid side effects very carefully until it is
75470 		 * referenced.
75471 		 */
75472 		env = duk_hobjenv_alloc(thr,
75473 		                        DUK_HOBJECT_FLAG_EXTENSIBLE |
75474 		                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV));
75475 		DUK_ASSERT(env != NULL);
75476 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
75477 		env->target = target;  /* always provideThis=true */
75478 		DUK_HOBJECT_INCREF(thr, target);
75479 		env->has_this = 1;
75480 		DUK_ASSERT_HOBJENV_VALID(env);
75481 		DUK_DDD(DUK_DDDPRINT("environment for with binding: %!iO", env));
75482 
75483 		DUK_ASSERT(act == thr->callstack_curr);
75484 		DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
75485 		DUK_ASSERT(act->lex_env != NULL);
75486 		DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, act->lex_env);
75487 		act->lex_env = (duk_hobject *) env;  /* Now reachable. */
75488 		DUK_HOBJECT_INCREF(thr, (duk_hobject *) env);
75489 		/* Net refcount change to act->lex_env is 0: incref for env's
75490 		 * prototype, decref for act->lex_env overwrite.
75491 		 */
75492 
75493 		/* Set catcher lex_env active (affects unwind)
75494 		 * only when the whole setup is complete.
75495 		 */
75496 		cat = act->cat;  /* XXX: better to relookup? not mandatory because 'cat' is stable */
75497 		cat->flags |= DUK_CAT_FLAG_LEXENV_ACTIVE;
75498 	} else {
75499 		;
75500 	}
75501 
75502 	DUK_DDD(DUK_DDDPRINT("TRYCATCH catcher: flags=0x%08lx, pc_base=%ld, "
75503 	                     "idx_base=%ld, h_varname=%!O",
75504 	                     (unsigned long) cat->flags,
75505 	                     (long) cat->pc_base, (long) cat->idx_base, (duk_heaphdr *) cat->h_varname));
75506 
75507 	duk_pop_unsafe(thr);
75508 }
75509 
75510 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endtry(duk_hthread *thr, duk_uint_fast32_t ins) {
75511 	duk_activation *act;
75512 	duk_catcher *cat;
75513 	duk_tval *tv1;
75514 	duk_instr_t *pc_base;
75515 
75516 	DUK_UNREF(ins);
75517 
75518 	DUK_ASSERT(thr->callstack_top >= 1);
75519 	act = thr->callstack_curr;
75520 	DUK_ASSERT(act != NULL);
75521 	cat = act->cat;
75522 	DUK_ASSERT(cat != NULL);
75523 	DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_TCF);
75524 
75525 	DUK_DDD(DUK_DDDPRINT("ENDTRY: clearing catch active flag (regardless of whether it was set or not)"));
75526 	DUK_CAT_CLEAR_CATCH_ENABLED(cat);
75527 
75528 	pc_base = cat->pc_base;
75529 
75530 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75531 		DUK_DDD(DUK_DDDPRINT("ENDTRY: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
75532 
75533 		tv1 = thr->valstack + cat->idx_base;
75534 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75535 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
75536 		tv1 = NULL;
75537 
75538 		tv1 = thr->valstack + cat->idx_base + 1;
75539 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75540 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
75541 		tv1 = NULL;
75542 
75543 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
75544 	} else {
75545 		DUK_DDD(DUK_DDDPRINT("ENDTRY: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
75546 
75547 		duk_hthread_catcher_unwind_norz(thr, act);  /* lexenv may be set for 'with' binding */
75548 		/* no need to unwind callstack */
75549 	}
75550 
75551 	return pc_base + 1;  /* new curr_pc value */
75552 }
75553 
75554 DUK_LOCAL DUK__NOINLINE_PERF duk_instr_t *duk__handle_op_endcatch(duk_hthread *thr, duk_uint_fast32_t ins) {
75555 	duk_activation *act;
75556 	duk_catcher *cat;
75557 	duk_tval *tv1;
75558 	duk_instr_t *pc_base;
75559 
75560 	DUK_UNREF(ins);
75561 
75562 	DUK_ASSERT(thr->callstack_top >= 1);
75563 	act = thr->callstack_curr;
75564 	DUK_ASSERT(act != NULL);
75565 	cat = act->cat;
75566 	DUK_ASSERT(cat != NULL);
75567 	DUK_ASSERT(!DUK_CAT_HAS_CATCH_ENABLED(cat));  /* cleared before entering catch part */
75568 
75569 	if (DUK_CAT_HAS_LEXENV_ACTIVE(cat)) {
75570 		duk_hobject *prev_env;
75571 
75572 		/* 'with' binding has no catch clause, so can't be here unless a normal try-catch */
75573 		DUK_ASSERT(DUK_CAT_HAS_CATCH_BINDING_ENABLED(cat));
75574 		DUK_ASSERT(act->lex_env != NULL);
75575 
75576 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: popping catcher part lexical environment"));
75577 
75578 		prev_env = act->lex_env;
75579 		DUK_ASSERT(prev_env != NULL);
75580 		act->lex_env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, prev_env);
75581 		DUK_CAT_CLEAR_LEXENV_ACTIVE(cat);
75582 		DUK_HOBJECT_INCREF(thr, act->lex_env);
75583 		DUK_HOBJECT_DECREF(thr, prev_env);  /* side effects */
75584 
75585 		DUK_ASSERT(act == thr->callstack_curr);
75586 		DUK_ASSERT(act != NULL);
75587 	}
75588 
75589 	pc_base = cat->pc_base;
75590 
75591 	if (DUK_CAT_HAS_FINALLY_ENABLED(cat)) {
75592 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: finally part is active, jump through 2nd jump slot with 'normal continuation'"));
75593 
75594 		tv1 = thr->valstack + cat->idx_base;
75595 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75596 		DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
75597 		tv1 = NULL;
75598 
75599 		tv1 = thr->valstack + cat->idx_base + 1;
75600 		DUK_ASSERT(tv1 >= thr->valstack && tv1 < thr->valstack_top);
75601 		DUK_TVAL_SET_U32_UPDREF(thr, tv1, (duk_uint32_t) DUK_LJ_TYPE_NORMAL);  /* side effects */
75602 		tv1 = NULL;
75603 
75604 		DUK_CAT_CLEAR_FINALLY_ENABLED(cat);
75605 	} else {
75606 		DUK_DDD(DUK_DDDPRINT("ENDCATCH: no finally part, dismantle catcher, jump through 2nd jump slot (to end of statement)"));
75607 
75608 		duk_hthread_catcher_unwind_norz(thr, act);
75609 		/* no need to unwind callstack */
75610 	}
75611 
75612 	return pc_base + 1;  /* new curr_pc value */
75613 }
75614 
75615 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) {
75616 	duk_activation *act;
75617 	duk_tval *tv1;
75618 	duk_uint_t reg_catch;
75619 	duk_small_uint_t cont_type;
75620 	duk_small_uint_t ret_result;
75621 
75622 	DUK_ASSERT(thr->ptr_curr_pc == NULL);
75623 	DUK_ASSERT(thr->callstack_top >= 1);
75624 	act = thr->callstack_curr;
75625 	DUK_ASSERT(act != NULL);
75626 	reg_catch = DUK_DEC_ABC(ins);
75627 
75628 	/* CATCH flag may be enabled or disabled here; it may be enabled if
75629 	 * the statement has a catch block but the try block does not throw
75630 	 * an error.
75631 	 */
75632 
75633 	DUK_DDD(DUK_DDDPRINT("ENDFIN: completion value=%!T, type=%!T",
75634 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 0),
75635 	                     (duk_tval *) (thr->valstack_bottom + reg_catch + 1)));
75636 
75637 	tv1 = thr->valstack_bottom + reg_catch + 1;  /* type */
75638 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
75639 #if defined(DUK_USE_FASTINT)
75640 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
75641 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
75642 #else
75643 	cont_type = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
75644 #endif
75645 
75646 	tv1--;  /* value */
75647 
75648 	switch (cont_type) {
75649 	case DUK_LJ_TYPE_NORMAL: {
75650 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'normal' (non-abrupt) completion -> "
75651 		                     "dismantle catcher, resume execution after ENDFIN"));
75652 
75653 		duk_hthread_catcher_unwind_norz(thr, act);
75654 		/* no need to unwind callstack */
75655 		return 0;  /* restart execution */
75656 	}
75657 	case DUK_LJ_TYPE_RETURN: {
75658 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with 'return' complation -> dismantle "
75659 		                     "catcher, handle return, lj.value1=%!T", tv1));
75660 
75661 		/* Not necessary to unwind catch stack: return handling will
75662 		 * do it.  The finally flag of 'cat' is no longer set.  The
75663 		 * catch flag may be set, but it's not checked by return handling.
75664 		 */
75665 
75666 		duk_push_tval(thr, tv1);
75667 		ret_result = duk__handle_return(thr, entry_act);
75668 		if (ret_result == DUK__RETHAND_RESTART) {
75669 			return 0;  /* restart execution */
75670 		}
75671 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED);
75672 
75673 		DUK_DDD(DUK_DDDPRINT("exiting executor after ENDFIN and RETURN (pseudo) longjmp type"));
75674 		return 1;  /* exit executor */
75675 	}
75676 	case DUK_LJ_TYPE_BREAK:
75677 	case DUK_LJ_TYPE_CONTINUE: {
75678 		duk_uint_t label_id;
75679 		duk_small_uint_t lj_type;
75680 
75681 		/* Not necessary to unwind catch stack: break/continue
75682 		 * handling will do it.  The finally flag of 'cat' is
75683 		 * no longer set.  The catch flag may be set, but it's
75684 		 * not checked by break/continue handling.
75685 		 */
75686 
75687 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
75688 #if defined(DUK_USE_FASTINT)
75689 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
75690 		label_id = (duk_small_uint_t) DUK_TVAL_GET_FASTINT_U32(tv1);
75691 #else
75692 		label_id = (duk_small_uint_t) DUK_TVAL_GET_NUMBER(tv1);
75693 #endif
75694 		lj_type = cont_type;
75695 		duk__handle_break_or_continue(thr, label_id, lj_type);
75696 		return 0;  /* restart execution */
75697 	}
75698 	default: {
75699 		DUK_DDD(DUK_DDDPRINT("ENDFIN: finally part finishing with abrupt completion, lj_type=%ld -> "
75700 		                     "dismantle catcher, re-throw error",
75701 		                     (long) cont_type));
75702 
75703 		duk_err_setup_ljstate1(thr, (duk_small_uint_t) cont_type, tv1);
75704 		/* No debugger Throw notify check on purpose (rethrow). */
75705 
75706 		DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
75707 		duk_err_longjmp(thr);
75708 		DUK_UNREACHABLE();
75709 	}
75710 	}
75711 
75712 	DUK_UNREACHABLE();
75713 	return 0;
75714 }
75715 
75716 DUK_LOCAL DUK__NOINLINE_PERF void duk__handle_op_initenum(duk_hthread *thr, duk_uint_fast32_t ins) {
75717 	duk_small_uint_t b;
75718 	duk_small_uint_t c;
75719 
75720 	/*
75721 	 *  Enumeration semantics come from for-in statement, E5 Section 12.6.4.
75722 	 *  If called with 'null' or 'undefined', this opcode returns 'null' as
75723 	 *  the enumerator, which is special cased in NEXTENUM.  This simplifies
75724 	 *  the compiler part
75725 	 */
75726 
75727 	/* B -> register for writing enumerator object
75728 	 * C -> value to be enumerated (register)
75729 	 */
75730 	b = DUK_DEC_B(ins);
75731 	c = DUK_DEC_C(ins);
75732 
75733 	if (duk_is_null_or_undefined(thr, (duk_idx_t) c)) {
75734 		duk_push_null(thr);
75735 		duk_replace(thr, (duk_idx_t) b);
75736 	} else {
75737 		duk_dup(thr, (duk_idx_t) c);
75738 		duk_to_object(thr, -1);
75739 		duk_hobject_enumerator_create(thr, 0 /*enum_flags*/);  /* [ ... val ] --> [ ... enum ] */
75740 		duk_replace(thr, (duk_idx_t) b);
75741 	}
75742 }
75743 
75744 DUK_LOCAL DUK__NOINLINE_PERF duk_small_uint_t duk__handle_op_nextenum(duk_hthread *thr, duk_uint_fast32_t ins) {
75745 	duk_small_uint_t b;
75746 	duk_small_uint_t c;
75747 	duk_small_uint_t pc_skip = 0;
75748 
75749 	/*
75750 	 *  NEXTENUM checks whether the enumerator still has unenumerated
75751 	 *  keys.  If so, the next key is loaded to the target register
75752 	 *  and the next instruction is skipped.  Otherwise the next instruction
75753 	 *  will be executed, jumping out of the enumeration loop.
75754 	 */
75755 
75756 	/* B -> target register for next key
75757 	 * C -> enum register
75758 	 */
75759 	b = DUK_DEC_B(ins);
75760 	c = DUK_DEC_C(ins);
75761 
75762 	DUK_DDD(DUK_DDDPRINT("NEXTENUM: b->%!T, c->%!T",
75763 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) b),
75764 	                     (duk_tval *) duk_get_tval(thr, (duk_idx_t) c)));
75765 
75766 	if (duk_is_object(thr, (duk_idx_t) c)) {
75767 		/* XXX: assert 'c' is an enumerator */
75768 		duk_dup(thr, (duk_idx_t) c);
75769 		if (duk_hobject_enumerator_next(thr, 0 /*get_value*/)) {
75770 			/* [ ... enum ] -> [ ... next_key ] */
75771 			DUK_DDD(DUK_DDDPRINT("enum active, next key is %!T, skip jump slot ",
75772 			                     (duk_tval *) duk_get_tval(thr, -1)));
75773 			pc_skip = 1;
75774 		} else {
75775 			/* [ ... enum ] -> [ ... ] */
75776 			DUK_DDD(DUK_DDDPRINT("enum finished, execute jump slot"));
75777 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
75778 			thr->valstack_top++;
75779 		}
75780 		duk_replace(thr, (duk_idx_t) b);
75781 	} else {
75782 		/* 'null' enumerator case -> behave as with an empty enumerator */
75783 		DUK_ASSERT(duk_is_null(thr, (duk_idx_t) c));
75784 		DUK_DDD(DUK_DDDPRINT("enum is null, execute jump slot"));
75785 	}
75786 
75787 	return pc_skip;
75788 }
75789 
75790 /*
75791  *  Call handling helpers.
75792  */
75793 
75794 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) {
75795 	duk_bool_t rc;
75796 
75797 	duk_set_top_unsafe(thr, (duk_idx_t) (idx + nargs + 2));   /* [ ... func this arg1 ... argN ] */
75798 
75799 	/* Attempt an Ecma-to-Ecma call setup.  If the call
75800 	 * target is (directly or indirectly) Reflect.construct(),
75801 	 * the call may change into a constructor call on the fly.
75802 	 */
75803 	rc = (duk_bool_t) duk_handle_call_unprotected(thr, idx, call_flags);
75804 	if (rc != 0) {
75805 		/* Ecma-to-ecma call possible, may or may not
75806 		 * be a tail call.  Avoid C recursion by
75807 		 * reusing current executor instance.
75808 		 */
75809 		DUK_DDD(DUK_DDDPRINT("ecma-to-ecma call setup possible, restart execution"));
75810 		/* curr_pc synced by duk_handle_call_unprotected() */
75811 		DUK_ASSERT(thr->ptr_curr_pc == NULL);
75812 		return rc;
75813 	} else {
75814 		/* Call was handled inline. */
75815 	}
75816 	DUK_ASSERT(thr->ptr_curr_pc != NULL);
75817 	return rc;
75818 }
75819 
75820 /*
75821  *  ECMAScript bytecode executor.
75822  *
75823  *  Resume execution for the current thread from its current activation.
75824  *  Returns when execution would return from the entry level activation,
75825  *  leaving a single return value on top of the stack.  Function calls
75826  *  and thread resumptions are handled internally.  If an error occurs,
75827  *  a longjmp() with type DUK_LJ_TYPE_THROW is called on the entry level
75828  *  setjmp() jmpbuf.
75829  *
75830  *  ECMAScript function calls and coroutine resumptions are handled
75831  *  internally (by the outer executor function) without recursive C calls.
75832  *  Other function calls are handled using duk_handle_call(), increasing
75833  *  C recursion depth.
75834  *
75835  *  Abrupt completions (= long control tranfers) are handled either
75836  *  directly by reconfiguring relevant stacks and restarting execution,
75837  *  or via a longjmp.  Longjmp-free handling is preferable for performance
75838  *  (especially Emscripten performance), and is used for: break, continue,
75839  *  and return.
75840  *
75841  *  For more detailed notes, see doc/execution.rst.
75842  *
75843  *  Also see doc/code-issues.rst for discussion of setjmp(), longjmp(),
75844  *  and volatile.
75845  */
75846 
75847 /* Presence of 'fun' is config based, there's a marginal performance
75848  * difference and the best option is architecture dependent.
75849  */
75850 #if defined(DUK_USE_EXEC_FUN_LOCAL)
75851 #define DUK__FUN()          fun
75852 #else
75853 #define DUK__FUN()          ((duk_hcompfunc *) DUK_ACT_GET_FUNC((thr)->callstack_curr))
75854 #endif
75855 
75856 /* Strict flag. */
75857 #define DUK__STRICT()       ((duk_small_uint_t) DUK_HOBJECT_HAS_STRICT((duk_hobject *) DUK__FUN()))
75858 
75859 /* Reg/const access macros: these are very footprint and performance sensitive
75860  * so modify with care.  Arguments are sometimes evaluated multiple times which
75861  * is not ideal.
75862  */
75863 #define DUK__REG(x)         (*(thr->valstack_bottom + (x)))
75864 #define DUK__REGP(x)        (thr->valstack_bottom + (x))
75865 #define DUK__CONST(x)       (*(consts + (x)))
75866 #define DUK__CONSTP(x)      (consts + (x))
75867 
75868 /* Reg/const access macros which take the 32-bit instruction and avoid an
75869  * explicit field decoding step by using shifts and masks.  These must be
75870  * kept in sync with duk_js_bytecode.h.  The shift/mask values are chosen
75871  * so that 'ins' can be shifted and masked and used as a -byte- offset
75872  * instead of a duk_tval offset which needs further shifting (which is an
75873  * issue on some, but not all, CPUs).
75874  */
75875 #define DUK__RCBIT_B           DUK_BC_REGCONST_B
75876 #define DUK__RCBIT_C           DUK_BC_REGCONST_C
75877 #if defined(DUK_USE_EXEC_REGCONST_OPTIMIZE)
75878 #if defined(DUK_USE_PACKED_TVAL)
75879 #define DUK__TVAL_SHIFT        3  /* sizeof(duk_tval) == 8 */
75880 #else
75881 #define DUK__TVAL_SHIFT        4  /* sizeof(duk_tval) == 16; not always the case so also asserted for */
75882 #endif
75883 #define DUK__SHIFT_A           (DUK_BC_SHIFT_A - DUK__TVAL_SHIFT)
75884 #define DUK__SHIFT_B           (DUK_BC_SHIFT_B - DUK__TVAL_SHIFT)
75885 #define DUK__SHIFT_C           (DUK_BC_SHIFT_C - DUK__TVAL_SHIFT)
75886 #define DUK__SHIFT_BC          (DUK_BC_SHIFT_BC - DUK__TVAL_SHIFT)
75887 #define DUK__MASK_A            (DUK_BC_UNSHIFTED_MASK_A << DUK__TVAL_SHIFT)
75888 #define DUK__MASK_B            (DUK_BC_UNSHIFTED_MASK_B << DUK__TVAL_SHIFT)
75889 #define DUK__MASK_C            (DUK_BC_UNSHIFTED_MASK_C << DUK__TVAL_SHIFT)
75890 #define DUK__MASK_BC           (DUK_BC_UNSHIFTED_MASK_BC << DUK__TVAL_SHIFT)
75891 #define DUK__BYTEOFF_A(ins)    (((ins) >> DUK__SHIFT_A) & DUK__MASK_A)
75892 #define DUK__BYTEOFF_B(ins)    (((ins) >> DUK__SHIFT_B) & DUK__MASK_B)
75893 #define DUK__BYTEOFF_C(ins)    (((ins) >> DUK__SHIFT_C) & DUK__MASK_C)
75894 #define DUK__BYTEOFF_BC(ins)   (((ins) >> DUK__SHIFT_BC) & DUK__MASK_BC)
75895 
75896 #define DUK__REGP_A(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_A((ins))))
75897 #define DUK__REGP_B(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_B((ins))))
75898 #define DUK__REGP_C(ins)       ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_C((ins))))
75899 #define DUK__REGP_BC(ins)      ((duk_tval *) (void *) ((duk_uint8_t *) thr->valstack_bottom + DUK__BYTEOFF_BC((ins))))
75900 #define DUK__CONSTP_A(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_A((ins))))
75901 #define DUK__CONSTP_B(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_B((ins))))
75902 #define DUK__CONSTP_C(ins)     ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_C((ins))))
75903 #define DUK__CONSTP_BC(ins)    ((duk_tval *) (void *) ((duk_uint8_t *) consts + DUK__BYTEOFF_BC((ins))))
75904 #define DUK__REGCONSTP_B(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_B((ins))))
75905 #define DUK__REGCONSTP_C(ins)  ((duk_tval *) (void *) ((duk_uint8_t *) (((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK__BYTEOFF_C((ins))))
75906 #else  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
75907 /* Safe alternatives, no assumption about duk_tval size. */
75908 #define DUK__REGP_A(ins)       DUK__REGP(DUK_DEC_A((ins)))
75909 #define DUK__REGP_B(ins)       DUK__REGP(DUK_DEC_B((ins)))
75910 #define DUK__REGP_C(ins)       DUK__REGP(DUK_DEC_C((ins)))
75911 #define DUK__REGP_BC(ins)      DUK__REGP(DUK_DEC_BC((ins)))
75912 #define DUK__CONSTP_A(ins)     DUK__CONSTP(DUK_DEC_A((ins)))
75913 #define DUK__CONSTP_B(ins)     DUK__CONSTP(DUK_DEC_B((ins)))
75914 #define DUK__CONSTP_C(ins)     DUK__CONSTP(DUK_DEC_C((ins)))
75915 #define DUK__CONSTP_BC(ins)    DUK__CONSTP(DUK_DEC_BC((ins)))
75916 #define DUK__REGCONSTP_B(ins)  ((((ins) & DUK__RCBIT_B) ? consts : thr->valstack_bottom) + DUK_DEC_B((ins)))
75917 #define DUK__REGCONSTP_C(ins)  ((((ins) & DUK__RCBIT_C) ? consts : thr->valstack_bottom) + DUK_DEC_C((ins)))
75918 #endif  /* DUK_USE_EXEC_REGCONST_OPTIMIZE */
75919 
75920 #if defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
75921 #define DUK__INTERNAL_ERROR(msg)  do { \
75922 		DUK_ERROR_ERROR(thr, (msg)); \
75923 		DUK_WO_NORETURN(return;); \
75924 	} while (0)
75925 #else
75926 #define DUK__INTERNAL_ERROR(msg)  do { \
75927 		goto internal_error; \
75928 	} while (0)
75929 #endif
75930 
75931 #define DUK__SYNC_CURR_PC()  do { \
75932 		duk_activation *duk__act; \
75933 		duk__act = thr->callstack_curr; \
75934 		duk__act->curr_pc = curr_pc; \
75935 	} while (0)
75936 #define DUK__SYNC_AND_NULL_CURR_PC()  do { \
75937 		duk_activation *duk__act; \
75938 		duk__act = thr->callstack_curr; \
75939 		duk__act->curr_pc = curr_pc; \
75940 		thr->ptr_curr_pc = NULL; \
75941 	} while (0)
75942 
75943 #if defined(DUK_USE_EXEC_PREFER_SIZE)
75944 #define DUK__LOOKUP_INDIRECT(idx) do { \
75945 		(idx) = (duk_uint_fast_t) duk_get_uint(thr, (duk_idx_t) (idx)); \
75946 	} while (0)
75947 #elif defined(DUK_USE_FASTINT)
75948 #define DUK__LOOKUP_INDIRECT(idx) do { \
75949 		duk_tval *tv_ind; \
75950 		tv_ind = DUK__REGP((idx)); \
75951 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
75952 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv_ind));  /* compiler guarantees */ \
75953 		(idx) = (duk_uint_fast_t) DUK_TVAL_GET_FASTINT_U32(tv_ind); \
75954 	} while (0)
75955 #else
75956 #define DUK__LOOKUP_INDIRECT(idx) do { \
75957 		duk_tval *tv_ind; \
75958 		tv_ind = DUK__REGP(idx); \
75959 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_ind)); \
75960 		idx = (duk_uint_fast_t) DUK_TVAL_GET_NUMBER(tv_ind); \
75961 	} while (0)
75962 #endif
75963 
75964 DUK_LOCAL void duk__handle_executor_error(duk_heap *heap,
75965                                           duk_activation *entry_act,
75966                                           duk_int_t entry_call_recursion_depth,
75967                                           duk_jmpbuf *entry_jmpbuf_ptr) {
75968 	duk_small_uint_t lj_ret;
75969 
75970 	/* Longjmp callers are required to sync-and-null thr->ptr_curr_pc
75971 	 * before longjmp.
75972 	 */
75973 	DUK_ASSERT(heap->curr_thread != NULL);
75974 	DUK_ASSERT(heap->curr_thread->ptr_curr_pc == NULL);
75975 
75976 	/* XXX: signalling the need to shrink check (only if unwound) */
75977 
75978 	/* Must be restored here to handle e.g. yields properly. */
75979 	heap->call_recursion_depth = entry_call_recursion_depth;
75980 
75981 	/* Switch to caller's setjmp() catcher so that if an error occurs
75982 	 * during error handling, it is always propagated outwards instead
75983 	 * of causing an infinite loop in our own handler.
75984 	 */
75985 	heap->lj.jmpbuf_ptr = (duk_jmpbuf *) entry_jmpbuf_ptr;
75986 
75987 	lj_ret = duk__handle_longjmp(heap->curr_thread, entry_act);
75988 
75989 	/* Error handling complete, remove side effect protections.
75990 	 */
75991 #if defined(DUK_USE_ASSERTIONS)
75992 	DUK_ASSERT(heap->error_not_allowed == 1);
75993 	heap->error_not_allowed = 0;
75994 #endif
75995 	DUK_ASSERT(heap->pf_prevent_count > 0);
75996 	heap->pf_prevent_count--;
75997 	DUK_DD(DUK_DDPRINT("executor error handled, pf_prevent_count updated to %ld", (long) heap->pf_prevent_count));
75998 
75999 	if (lj_ret == DUK__LONGJMP_RESTART) {
76000 		/* Restart bytecode execution, possibly with a changed thread. */
76001 		DUK_REFZERO_CHECK_SLOW(heap->curr_thread);
76002 	} else {
76003 		/* If an error is propagated, don't run refzero checks here.
76004 		 * The next catcher will deal with that.  Pf_prevent_count
76005 		 * will be re-bumped by the longjmp.
76006 		 */
76007 
76008 		DUK_ASSERT(lj_ret == DUK__LONGJMP_RETHROW);  /* Rethrow error to calling state. */
76009 		DUK_ASSERT(heap->lj.jmpbuf_ptr == entry_jmpbuf_ptr);  /* Longjmp handling has restored jmpbuf_ptr. */
76010 
76011 		/* Thread may have changed, e.g. YIELD converted to THROW. */
76012 		duk_err_longjmp(heap->curr_thread);
76013 		DUK_UNREACHABLE();
76014 	}
76015 }
76016 
76017 /* Outer executor with setjmp/longjmp handling. */
76018 DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
76019 	/* Entry level info. */
76020 	duk_hthread *entry_thread;
76021 	duk_activation *entry_act;
76022 	duk_int_t entry_call_recursion_depth;
76023 	duk_jmpbuf *entry_jmpbuf_ptr;
76024 	duk_jmpbuf our_jmpbuf;
76025 	duk_heap *heap;
76026 
76027 	DUK_ASSERT(exec_thr != NULL);
76028 	DUK_ASSERT(exec_thr->heap != NULL);
76029 	DUK_ASSERT(exec_thr->heap->curr_thread != NULL);
76030 	DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR((duk_heaphdr *) exec_thr);
76031 	DUK_ASSERT(exec_thr->callstack_top >= 1);  /* at least one activation, ours */
76032 	DUK_ASSERT(exec_thr->callstack_curr != NULL);
76033 	DUK_ASSERT(DUK_ACT_GET_FUNC(exec_thr->callstack_curr) != NULL);
76034 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(exec_thr->callstack_curr)));
76035 
76036 	DUK_GC_TORTURE(exec_thr->heap);
76037 
76038 	entry_thread = exec_thr;
76039 	heap = entry_thread->heap;
76040 	entry_act = entry_thread->callstack_curr;
76041 	DUK_ASSERT(entry_act != NULL);
76042 	entry_call_recursion_depth = entry_thread->heap->call_recursion_depth;
76043 	entry_jmpbuf_ptr = entry_thread->heap->lj.jmpbuf_ptr;
76044 
76045 	/*
76046 	 *  Note: we currently assume that the setjmp() catchpoint is
76047 	 *  not re-entrant (longjmp() cannot be called more than once
76048 	 *  for a single setjmp()).
76049 	 *
76050 	 *  See doc/code-issues.rst for notes on variable assignment
76051 	 *  before and after setjmp().
76052 	 */
76053 
76054 	for (;;) {
76055 		heap->lj.jmpbuf_ptr = &our_jmpbuf;
76056 		DUK_ASSERT(heap->lj.jmpbuf_ptr != NULL);
76057 
76058 #if defined(DUK_USE_CPP_EXCEPTIONS)
76059 		try {
76060 #else
76061 		DUK_ASSERT(heap->lj.jmpbuf_ptr == &our_jmpbuf);
76062 		if (DUK_SETJMP(our_jmpbuf.jb) == 0) {
76063 #endif
76064 			/* Execute bytecode until returned or longjmp(). */
76065 			duk__js_execute_bytecode_inner(entry_thread, entry_act);
76066 
76067 			/* Successful return: restore jmpbuf and return to caller. */
76068 			heap->lj.jmpbuf_ptr = entry_jmpbuf_ptr;
76069 
76070 			return;
76071 #if defined(DUK_USE_CPP_EXCEPTIONS)
76072 		} catch (duk_internal_exception &exc) {
76073 #else
76074 		} else {
76075 #endif
76076 #if defined(DUK_USE_CPP_EXCEPTIONS)
76077 			DUK_UNREF(exc);
76078 #endif
76079 			DUK_DDD(DUK_DDDPRINT("longjmp caught by bytecode executor"));
76080 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76081 
76082 			duk__handle_executor_error(heap,
76083 			                           entry_act,
76084 			                           entry_call_recursion_depth,
76085 			                           entry_jmpbuf_ptr);
76086 		}
76087 #if defined(DUK_USE_CPP_EXCEPTIONS)
76088 		catch (duk_fatal_exception &exc) {
76089 			DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
76090 			throw;
76091 		} catch (std::exception &exc) {
76092 			const char *what = exc.what();
76093 			if (!what) {
76094 				what = "unknown";
76095 			}
76096 			DUK_D(DUK_DPRINT("unexpected c++ std::exception (perhaps thrown by user code)"));
76097 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76098 			try {
76099 				DUK_ASSERT(heap->curr_thread != NULL);
76100 				DUK_ERROR_FMT1(heap->curr_thread, DUK_ERR_TYPE_ERROR, "caught invalid c++ std::exception '%s' (perhaps thrown by user code)", what);
76101 				DUK_WO_NORETURN(return;);
76102 			} catch (duk_internal_exception exc) {
76103 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ std::exception"));
76104 				DUK_UNREF(exc);
76105 				duk__handle_executor_error(heap,
76106 				                           entry_act,
76107 				                           entry_call_recursion_depth,
76108 				                           entry_jmpbuf_ptr);
76109 			}
76110 		} catch (...) {
76111 			DUK_D(DUK_DPRINT("unexpected c++ exception (perhaps thrown by user code)"));
76112 			DUK_STATS_INC(exec_thr->heap, stats_exec_throw);
76113 			try {
76114 				DUK_ASSERT(heap->curr_thread != NULL);
76115 				DUK_ERROR_TYPE(heap->curr_thread, "caught invalid c++ exception (perhaps thrown by user code)");
76116 				DUK_WO_NORETURN(return;);
76117 			} catch (duk_internal_exception exc) {
76118 				DUK_D(DUK_DPRINT("caught api error thrown from unexpected c++ exception"));
76119 				DUK_UNREF(exc);
76120 				duk__handle_executor_error(heap,
76121 				                           entry_act,
76122 				                           entry_call_recursion_depth,
76123 				                           entry_jmpbuf_ptr);
76124 			}
76125 		}
76126 #endif
76127 	}
76128 
76129 	DUK_WO_NORETURN(return;);
76130 }
76131 
76132 /* Inner executor, performance critical. */
76133 DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *entry_thread, duk_activation *entry_act) {
76134 	/* Current PC, accessed by other functions through thr->ptr_to_curr_pc.
76135 	 * Critical for performance.  It would be safest to make this volatile,
76136 	 * but that eliminates performance benefits; aliasing guarantees
76137 	 * should be enough though.
76138 	 */
76139 	duk_instr_t *curr_pc;         /* bytecode has a stable pointer */
76140 
76141 	/* Hot variables for interpretation.  Critical for performance,
76142 	 * but must add sparingly to minimize register shuffling.
76143 	 */
76144 	duk_hthread *thr;             /* stable */
76145 	duk_tval *consts;             /* stable */
76146 	duk_uint_fast32_t ins;
76147 	/* 'funcs' is quite rarely used, so no local for it */
76148 #if defined(DUK_USE_EXEC_FUN_LOCAL)
76149 	duk_hcompfunc *fun;
76150 #else
76151 	/* 'fun' is quite rarely used, so no local for it */
76152 #endif
76153 
76154 #if defined(DUK_USE_INTERRUPT_COUNTER)
76155 	duk_int_t int_ctr;
76156 #endif
76157 
76158 #if defined(DUK_USE_ASSERTIONS)
76159 	duk_size_t valstack_top_base;    /* valstack top, should match before interpreting each op (no leftovers) */
76160 #endif
76161 
76162 	/* Optimized reg/const access macros assume sizeof(duk_tval) to be
76163 	 * either 8 or 16.  Heap allocation checks this even without asserts
76164 	 * enabled now because it can't be autodetected in duk_config.h.
76165 	 */
76166 #if 1
76167 #if defined(DUK_USE_PACKED_TVAL)
76168 	DUK_ASSERT(sizeof(duk_tval) == 8);
76169 #else
76170 	DUK_ASSERT(sizeof(duk_tval) == 16);
76171 #endif
76172 #endif
76173 
76174 	DUK_GC_TORTURE(entry_thread->heap);
76175 
76176 	/*
76177 	 *  Restart execution by reloading thread state.
76178 	 *
76179 	 *  Note that 'thr' and any thread configuration may have changed,
76180 	 *  so all local variables are suspect and we need to reinitialize.
76181 	 *
76182 	 *  The number of local variables should be kept to a minimum: if
76183 	 *  the variables are spilled, they will need to be loaded from
76184 	 *  memory anyway.
76185 	 *
76186 	 *  Any 'goto restart_execution;' code path in opcode dispatch must
76187 	 *  ensure 'curr_pc' is synced back to act->curr_pc before the goto
76188 	 *  takes place.
76189 	 *
76190 	 *  The interpreter must be very careful with memory pointers, as
76191 	 *  many pointers are not guaranteed to be 'stable' and may be
76192 	 *  reallocated and relocated on-the-fly quite easily (e.g. by a
76193 	 *  memory allocation or a property access).
76194 	 *
76195 	 *  The following are assumed to have stable pointers:
76196 	 *    - the current thread
76197 	 *    - the current function
76198 	 *    - the bytecode, constant table, inner function table of the
76199 	 *      current function (as they are a part of the function allocation)
76200 	 *
76201 	 *  The following are assumed to have semi-stable pointers:
76202 	 *    - the current activation entry: stable as long as callstack
76203 	 *      is not changed (reallocated by growing or shrinking), or
76204 	 *      by any garbage collection invocation (through finalizers)
76205 	 *    - Note in particular that ANY DECREF can invalidate the
76206 	 *      activation pointer, so for the most part a fresh lookup
76207 	 *      is required
76208 	 *
76209 	 *  The following are not assumed to have stable pointers at all:
76210 	 *    - the value stack (registers) of the current thread
76211 	 *
76212 	 *  See execution.rst for discussion.
76213 	 */
76214 
76215  restart_execution:
76216 
76217 	/* Lookup current thread; use the stable 'entry_thread' for this to
76218 	 * avoid clobber warnings.  Any valid, reachable 'thr' value would be
76219 	 * fine for this, so using 'entry_thread' is just to silence warnings.
76220 	 */
76221 	thr = entry_thread->heap->curr_thread;
76222 	DUK_ASSERT(thr != NULL);
76223 	DUK_ASSERT(thr->callstack_top >= 1);
76224 	DUK_ASSERT(thr->callstack_curr != NULL);
76225 	DUK_ASSERT(DUK_ACT_GET_FUNC(thr->callstack_curr) != NULL);
76226 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(DUK_ACT_GET_FUNC(thr->callstack_curr)));
76227 
76228 	DUK_GC_TORTURE(thr->heap);
76229 
76230 	thr->ptr_curr_pc = &curr_pc;
76231 
76232 	/* Relookup and initialize dispatch loop variables.  Debugger check. */
76233 	{
76234 		duk_activation *act;
76235 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
76236 		duk_hcompfunc *fun;
76237 #endif
76238 
76239 		/* Assume interrupt init/counter are properly initialized here. */
76240 		/* Assume that thr->valstack_bottom has been set-up before getting here. */
76241 
76242 		act = thr->callstack_curr;
76243 		DUK_ASSERT(act != NULL);
76244 		fun = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
76245 		DUK_ASSERT(fun != NULL);
76246 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == fun->nregs);
76247 		consts = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, fun);
76248 		DUK_ASSERT(consts != NULL);
76249 
76250 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76251 		if (DUK_UNLIKELY(duk_debug_is_attached(thr->heap) && !thr->heap->dbg_processing)) {
76252 			duk__executor_recheck_debugger(thr, act, fun);
76253 			DUK_ASSERT(act == thr->callstack_curr);
76254 			DUK_ASSERT(act != NULL);
76255 		}
76256 #endif  /* DUK_USE_DEBUGGER_SUPPORT */
76257 
76258 #if defined(DUK_USE_ASSERTIONS)
76259 		valstack_top_base = (duk_size_t) (thr->valstack_top - thr->valstack);
76260 #endif
76261 
76262 		/* Set up curr_pc for opcode dispatch. */
76263 		curr_pc = act->curr_pc;
76264 	}
76265 
76266 	DUK_DD(DUK_DDPRINT("restarting execution, thr %p, act idx %ld, fun %p,"
76267 	                   "consts %p, funcs %p, lev %ld, regbot %ld, regtop %ld, "
76268 	                   "preventcount=%ld",
76269 	                   (void *) thr,
76270 	                   (long) (thr->callstack_top - 1),
76271 	                   (void *) DUK__FUN(),
76272 	                   (void *) DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, DUK__FUN()),
76273 	                   (void *) DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, DUK__FUN()),
76274 	                   (long) (thr->callstack_top - 1),
76275 	                   (long) (thr->valstack_bottom - thr->valstack),
76276 	                   (long) (thr->valstack_top - thr->valstack),
76277 	                   (long) thr->callstack_preventcount));
76278 
76279 	/* Dispatch loop. */
76280 
76281 	for (;;) {
76282 		duk_uint8_t op;
76283 
76284 		DUK_ASSERT(thr->callstack_top >= 1);
76285 		DUK_ASSERT(thr->valstack_top - thr->valstack_bottom == DUK__FUN()->nregs);
76286 		DUK_ASSERT((duk_size_t) (thr->valstack_top - thr->valstack) == valstack_top_base);
76287 
76288 		/* Executor interrupt counter check, used to implement breakpoints,
76289 		 * debugging interface, execution timeouts, etc.  The counter is heap
76290 		 * specific but is maintained in the current thread to make the check
76291 		 * as fast as possible.  The counter is copied back to the heap struct
76292 		 * whenever a thread switch occurs by the DUK_HEAP_SWITCH_THREAD() macro.
76293 		 */
76294 #if defined(DUK_USE_INTERRUPT_COUNTER)
76295 		int_ctr = thr->interrupt_counter;
76296 		if (DUK_LIKELY(int_ctr > 0)) {
76297 			thr->interrupt_counter = int_ctr - 1;
76298 		} else {
76299 			/* Trigger at zero or below */
76300 			duk_small_uint_t exec_int_ret;
76301 
76302 			DUK_STATS_INC(thr->heap, stats_exec_interrupt);
76303 
76304 			/* Write curr_pc back for the debugger. */
76305 			{
76306 				duk_activation *act;
76307 				DUK_ASSERT(thr->callstack_top > 0);
76308 				act = thr->callstack_curr;
76309 				DUK_ASSERT(act != NULL);
76310 				act->curr_pc = (duk_instr_t *) curr_pc;
76311 			}
76312 
76313 			/* Forced restart caused by a function return; must recheck
76314 			 * debugger breakpoints before checking line transitions,
76315 			 * see GH-303.  Restart and then handle interrupt_counter
76316 			 * zero again.
76317 			 */
76318 #if defined(DUK_USE_DEBUGGER_SUPPORT)
76319 			if (thr->heap->dbg_force_restart) {
76320 				DUK_DD(DUK_DDPRINT("dbg_force_restart flag forced restart execution"));  /* GH-303 */
76321 				thr->heap->dbg_force_restart = 0;
76322 				goto restart_execution;
76323 			}
76324 #endif
76325 
76326 			exec_int_ret = duk__executor_interrupt(thr);
76327 			if (exec_int_ret == DUK__INT_RESTART) {
76328 				/* curr_pc synced back above */
76329 				goto restart_execution;
76330 			}
76331 		}
76332 #endif  /* DUK_USE_INTERRUPT_COUNTER */
76333 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
76334 		/* For cross-checking during development: ensure dispatch count
76335 		 * matches cumulative interrupt counter init value sums.
76336 		 */
76337 		thr->heap->inst_count_exec++;
76338 #endif
76339 
76340 #if defined(DUK_USE_ASSERTIONS) || defined(DUK_USE_DEBUG)
76341 		{
76342 			duk_activation *act;
76343 			act = thr->callstack_curr;
76344 			DUK_ASSERT(curr_pc >= DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN()));
76345 			DUK_ASSERT(curr_pc < DUK_HCOMPFUNC_GET_CODE_END(thr->heap, DUK__FUN()));
76346 			DUK_UNREF(act);  /* if debugging disabled */
76347 
76348 			DUK_DDD(DUK_DDDPRINT("executing bytecode: pc=%ld, ins=0x%08lx, op=%ld, valstack_top=%ld/%ld, nregs=%ld  -->  %!I",
76349 			                     (long) (curr_pc - DUK_HCOMPFUNC_GET_CODE_BASE(thr->heap, DUK__FUN())),
76350 			                     (unsigned long) *curr_pc,
76351 			                     (long) DUK_DEC_OP(*curr_pc),
76352 			                     (long) (thr->valstack_top - thr->valstack),
76353 			                     (long) (thr->valstack_end - thr->valstack),
76354 			                     (long) (DUK__FUN() ? DUK__FUN()->nregs : -1),
76355 			                     (duk_instr_t) *curr_pc));
76356 		}
76357 #endif
76358 
76359 #if defined(DUK_USE_ASSERTIONS)
76360 		/* Quite heavy assert: check valstack policy.  Improper
76361 		 * shuffle instructions can write beyond valstack_top/end
76362 		 * so this check catches them in the act.
76363 		 */
76364 		{
76365 			duk_tval *tv;
76366 			tv = thr->valstack_top;
76367 			while (tv != thr->valstack_end) {
76368 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv));
76369 				tv++;
76370 			}
76371 		}
76372 #endif
76373 
76374 		ins = *curr_pc++;
76375 		DUK_STATS_INC(thr->heap, stats_exec_opcodes);
76376 
76377 		/* Typing: use duk_small_(u)int_fast_t when decoding small
76378 		 * opcode fields (op, A, B, C, BC) which fit into 16 bits
76379 		 * and duk_(u)int_fast_t when decoding larger fields (e.g.
76380 		 * ABC).  Use unsigned variant by default, signed when the
76381 		 * value is used in signed arithmetic.  Using variable names
76382 		 * such as 'a', 'b', 'c', 'bc', etc makes it easier to spot
76383 		 * typing mismatches.
76384 		 */
76385 
76386 		/* Switch based on opcode.  Cast to 8-bit unsigned value and
76387 		 * use a fully populated case clauses so that the compiler
76388 		 * will (at least usually) omit a bounds check.
76389 		 */
76390 		op = (duk_uint8_t) DUK_DEC_OP(ins);
76391 		switch (op) {
76392 
76393 		/* Some useful macros.  These access inner executor variables
76394 		 * directly so they only apply within the executor.
76395 		 */
76396 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76397 #define DUK__REPLACE_TOP_A_BREAK() { goto replace_top_a; }
76398 #define DUK__REPLACE_TOP_BC_BREAK() { goto replace_top_bc; }
76399 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
76400 		duk_bool_t duk__bval; \
76401 		duk__bval = (bval); \
76402 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
76403 		duk_push_boolean(thr, duk__bval); \
76404 		DUK__REPLACE_TOP_A_BREAK(); \
76405 	}
76406 #else
76407 #define DUK__REPLACE_TOP_A_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins)); break; }
76408 #define DUK__REPLACE_TOP_BC_BREAK() { DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins)); break; }
76409 #define DUK__REPLACE_BOOL_A_BREAK(bval) { \
76410 		duk_bool_t duk__bval; \
76411 		duk_tval *duk__tvdst; \
76412 		duk__bval = (bval); \
76413 		DUK_ASSERT(duk__bval == 0 || duk__bval == 1); \
76414 		duk__tvdst = DUK__REGP_A(ins); \
76415 		DUK_TVAL_SET_BOOLEAN_UPDREF(thr, duk__tvdst, duk__bval); \
76416 		break; \
76417 	}
76418 #endif
76419 
76420 		/* XXX: 12 + 12 bit variant might make sense too, for both reg and
76421 		 * const loads.
76422 		 */
76423 
76424 		/* For LDREG, STREG, LDCONST footprint optimized variants would just
76425 		 * duk_dup() + duk_replace(), but because they're used quite a lot
76426 		 * they're currently intentionally not size optimized.
76427 		 */
76428 		case DUK_OP_LDREG: {
76429 			duk_tval *tv1, *tv2;
76430 
76431 			tv1 = DUK__REGP_A(ins);
76432 			tv2 = DUK__REGP_BC(ins);
76433 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76434 			break;
76435 		}
76436 
76437 		case DUK_OP_STREG: {
76438 			duk_tval *tv1, *tv2;
76439 
76440 			tv1 = DUK__REGP_A(ins);
76441 			tv2 = DUK__REGP_BC(ins);
76442 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv2, tv1);  /* side effects */
76443 			break;
76444 		}
76445 
76446 		case DUK_OP_LDCONST: {
76447 			duk_tval *tv1, *tv2;
76448 
76449 			tv1 = DUK__REGP_A(ins);
76450 			tv2 = DUK__CONSTP_BC(ins);
76451 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76452 			break;
76453 		}
76454 
76455 		/* LDINT and LDINTX are intended to load an arbitrary signed
76456 		 * 32-bit value.  Only an LDINT+LDINTX sequence is supported.
76457 		 * This also guarantees all values remain fastints.
76458 		 */
76459 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76460 		case DUK_OP_LDINT: {
76461 			duk_int32_t val;
76462 
76463 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
76464 			duk_push_int(thr, val);
76465 			DUK__REPLACE_TOP_A_BREAK();
76466 		}
76467 		case DUK_OP_LDINTX: {
76468 			duk_int32_t val;
76469 
76470 			val = (duk_int32_t) duk_get_int(thr, DUK_DEC_A(ins));
76471 			val = (val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
76472 			duk_push_int(thr, val);
76473 			DUK__REPLACE_TOP_A_BREAK();
76474 		}
76475 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76476 		case DUK_OP_LDINT: {
76477 			duk_tval *tv1;
76478 			duk_int32_t val;
76479 
76480 			val = (duk_int32_t) DUK_DEC_BC(ins) - (duk_int32_t) DUK_BC_LDINT_BIAS;
76481 			tv1 = DUK__REGP_A(ins);
76482 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
76483 			break;
76484 		}
76485 		case DUK_OP_LDINTX: {
76486 			duk_tval *tv1;
76487 			duk_int32_t val;
76488 
76489 			tv1 = DUK__REGP_A(ins);
76490 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
76491 #if defined(DUK_USE_FASTINT)
76492 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
76493 			val = DUK_TVAL_GET_FASTINT_I32(tv1);
76494 #else
76495 			/* XXX: fast double-to-int conversion, we know number is integer in [-0x80000000,0xffffffff]. */
76496 			val = (duk_int32_t) DUK_TVAL_GET_NUMBER(tv1);
76497 #endif
76498 			val = (duk_int32_t) ((duk_uint32_t) val << DUK_BC_LDINTX_SHIFT) + (duk_int32_t) DUK_DEC_BC(ins);  /* no bias */
76499 			DUK_TVAL_SET_I32_UPDREF(thr, tv1, val);  /* side effects */
76500 			break;
76501 		}
76502 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76503 
76504 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76505 		case DUK_OP_LDTHIS: {
76506 			duk_push_this(thr);
76507 			DUK__REPLACE_TOP_BC_BREAK();
76508 		}
76509 		case DUK_OP_LDUNDEF: {
76510 			duk_to_undefined(thr, (duk_idx_t) DUK_DEC_BC(ins));
76511 			break;
76512 		}
76513 		case DUK_OP_LDNULL: {
76514 			duk_to_null(thr, (duk_idx_t) DUK_DEC_BC(ins));
76515 			break;
76516 		}
76517 		case DUK_OP_LDTRUE: {
76518 			duk_push_true(thr);
76519 			DUK__REPLACE_TOP_BC_BREAK();
76520 		}
76521 		case DUK_OP_LDFALSE: {
76522 			duk_push_false(thr);
76523 			DUK__REPLACE_TOP_BC_BREAK();
76524 		}
76525 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76526 		case DUK_OP_LDTHIS: {
76527 			/* Note: 'this' may be bound to any value, not just an object */
76528 			duk_tval *tv1, *tv2;
76529 
76530 			tv1 = DUK__REGP_BC(ins);
76531 			tv2 = thr->valstack_bottom - 1;  /* 'this binding' is just under bottom */
76532 			DUK_ASSERT(tv2 >= thr->valstack);
76533 			DUK_TVAL_SET_TVAL_UPDREF_FAST(thr, tv1, tv2);  /* side effects */
76534 			break;
76535 		}
76536 		case DUK_OP_LDUNDEF: {
76537 			duk_tval *tv1;
76538 
76539 			tv1 = DUK__REGP_BC(ins);
76540 			DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv1);  /* side effects */
76541 			break;
76542 		}
76543 		case DUK_OP_LDNULL: {
76544 			duk_tval *tv1;
76545 
76546 			tv1 = DUK__REGP_BC(ins);
76547 			DUK_TVAL_SET_NULL_UPDREF(thr, tv1);  /* side effects */
76548 			break;
76549 		}
76550 		case DUK_OP_LDTRUE: {
76551 			duk_tval *tv1;
76552 
76553 			tv1 = DUK__REGP_BC(ins);
76554 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 1);  /* side effects */
76555 			break;
76556 		}
76557 		case DUK_OP_LDFALSE: {
76558 			duk_tval *tv1;
76559 
76560 			tv1 = DUK__REGP_BC(ins);
76561 			DUK_TVAL_SET_BOOLEAN_UPDREF(thr, tv1, 0);  /* side effects */
76562 			break;
76563 		}
76564 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76565 
76566 		case DUK_OP_BNOT: {
76567 			duk__vm_bitwise_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
76568 			break;
76569 		}
76570 
76571 		case DUK_OP_LNOT: {
76572 			duk__vm_logical_not(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins));
76573 			break;
76574 		}
76575 
76576 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76577 		case DUK_OP_UNM:
76578 		case DUK_OP_UNP: {
76579 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), op);
76580 			break;
76581 		}
76582 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76583 		case DUK_OP_UNM: {
76584 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNM);
76585 			break;
76586 		}
76587 		case DUK_OP_UNP: {
76588 			duk__vm_arith_unary_op(thr, DUK_DEC_BC(ins), DUK_DEC_A(ins), DUK_OP_UNP);
76589 			break;
76590 		}
76591 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76592 
76593 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76594 		case DUK_OP_TYPEOF: {
76595 			duk_small_uint_t stridx;
76596 
76597 			stridx = duk_js_typeof_stridx(DUK__REGP_BC(ins));
76598 			DUK_ASSERT_STRIDX_VALID(stridx);
76599 			duk_push_hstring_stridx(thr, stridx);
76600 			DUK__REPLACE_TOP_A_BREAK();
76601 		}
76602 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76603 		case DUK_OP_TYPEOF: {
76604 			duk_tval *tv;
76605 			duk_small_uint_t stridx;
76606 			duk_hstring *h_str;
76607 
76608 			tv = DUK__REGP_BC(ins);
76609 			stridx = duk_js_typeof_stridx(tv);
76610 			DUK_ASSERT_STRIDX_VALID(stridx);
76611 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
76612 			tv = DUK__REGP_A(ins);
76613 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
76614 			break;
76615 		}
76616 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76617 
76618 		case DUK_OP_TYPEOFID: {
76619 			duk_small_uint_t stridx;
76620 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
76621 			duk_hstring *h_str;
76622 #endif
76623 			duk_activation *act;
76624 			duk_hstring *name;
76625 			duk_tval *tv;
76626 
76627 			/* A -> target register
76628 			 * BC -> constant index of identifier name
76629 			 */
76630 
76631 			tv = DUK__CONSTP_BC(ins);
76632 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv));
76633 			name = DUK_TVAL_GET_STRING(tv);
76634 			tv = NULL;  /* lookup has side effects */
76635 			act = thr->callstack_curr;
76636 			if (duk_js_getvar_activation(thr, act, name, 0 /*throw*/)) {
76637 				/* -> [... val this] */
76638 				tv = DUK_GET_TVAL_NEGIDX(thr, -2);
76639 				stridx = duk_js_typeof_stridx(tv);
76640 				tv = NULL;  /* no longer needed */
76641 				duk_pop_2_unsafe(thr);
76642 			} else {
76643 				/* unresolvable, no stack changes */
76644 				stridx = DUK_STRIDX_LC_UNDEFINED;
76645 			}
76646 			DUK_ASSERT_STRIDX_VALID(stridx);
76647 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76648 			duk_push_hstring_stridx(thr, stridx);
76649 			DUK__REPLACE_TOP_A_BREAK();
76650 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76651 			h_str = DUK_HTHREAD_GET_STRING(thr, stridx);
76652 			tv = DUK__REGP_A(ins);
76653 			DUK_TVAL_SET_STRING_UPDREF(thr, tv, h_str);
76654 			break;
76655 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76656 		}
76657 
76658 		/* Equality: E5 Sections 11.9.1, 11.9.3 */
76659 
76660 #define DUK__EQ_BODY(barg,carg) { \
76661 		duk_bool_t tmp; \
76662 		tmp = duk_js_equals(thr, (barg), (carg)); \
76663 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76664 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76665 	}
76666 #define DUK__NEQ_BODY(barg,carg) { \
76667 		duk_bool_t tmp; \
76668 		tmp = duk_js_equals(thr, (barg), (carg)); \
76669 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76670 		tmp ^= 1; \
76671 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76672 	}
76673 #define DUK__SEQ_BODY(barg,carg) { \
76674 		duk_bool_t tmp; \
76675 		tmp = duk_js_strict_equals((barg), (carg)); \
76676 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76677 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76678 	}
76679 #define DUK__SNEQ_BODY(barg,carg) { \
76680 		duk_bool_t tmp; \
76681 		tmp = duk_js_strict_equals((barg), (carg)); \
76682 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76683 		tmp ^= 1; \
76684 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76685 	}
76686 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76687 		case DUK_OP_EQ_RR:
76688 		case DUK_OP_EQ_CR:
76689 		case DUK_OP_EQ_RC:
76690 		case DUK_OP_EQ_CC:
76691 			DUK__EQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76692 		case DUK_OP_NEQ_RR:
76693 		case DUK_OP_NEQ_CR:
76694 		case DUK_OP_NEQ_RC:
76695 		case DUK_OP_NEQ_CC:
76696 			DUK__NEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76697 		case DUK_OP_SEQ_RR:
76698 		case DUK_OP_SEQ_CR:
76699 		case DUK_OP_SEQ_RC:
76700 		case DUK_OP_SEQ_CC:
76701 			DUK__SEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76702 		case DUK_OP_SNEQ_RR:
76703 		case DUK_OP_SNEQ_CR:
76704 		case DUK_OP_SNEQ_RC:
76705 		case DUK_OP_SNEQ_CC:
76706 			DUK__SNEQ_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76707 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76708 		case DUK_OP_EQ_RR:
76709 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76710 		case DUK_OP_EQ_CR:
76711 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76712 		case DUK_OP_EQ_RC:
76713 			DUK__EQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76714 		case DUK_OP_EQ_CC:
76715 			DUK__EQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76716 		case DUK_OP_NEQ_RR:
76717 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76718 		case DUK_OP_NEQ_CR:
76719 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76720 		case DUK_OP_NEQ_RC:
76721 			DUK__NEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76722 		case DUK_OP_NEQ_CC:
76723 			DUK__NEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76724 		case DUK_OP_SEQ_RR:
76725 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76726 		case DUK_OP_SEQ_CR:
76727 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76728 		case DUK_OP_SEQ_RC:
76729 			DUK__SEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76730 		case DUK_OP_SEQ_CC:
76731 			DUK__SEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76732 		case DUK_OP_SNEQ_RR:
76733 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76734 		case DUK_OP_SNEQ_CR:
76735 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76736 		case DUK_OP_SNEQ_RC:
76737 			DUK__SNEQ_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76738 		case DUK_OP_SNEQ_CC:
76739 			DUK__SNEQ_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76740 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76741 
76742 #define DUK__COMPARE_BODY(arg1,arg2,flags) { \
76743 		duk_bool_t tmp; \
76744 		tmp = duk_js_compare_helper(thr, (arg1), (arg2), (flags)); \
76745 		DUK_ASSERT(tmp == 0 || tmp == 1); \
76746 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
76747 	}
76748 #define DUK__GT_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), 0)
76749 #define DUK__GE_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST | DUK_COMPARE_FLAG_NEGATE)
76750 #define DUK__LT_BODY(barg,carg) DUK__COMPARE_BODY((barg), (carg), DUK_COMPARE_FLAG_EVAL_LEFT_FIRST)
76751 #define DUK__LE_BODY(barg,carg) DUK__COMPARE_BODY((carg), (barg), DUK_COMPARE_FLAG_NEGATE)
76752 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76753 		case DUK_OP_GT_RR:
76754 		case DUK_OP_GT_CR:
76755 		case DUK_OP_GT_RC:
76756 		case DUK_OP_GT_CC:
76757 			DUK__GT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76758 		case DUK_OP_GE_RR:
76759 		case DUK_OP_GE_CR:
76760 		case DUK_OP_GE_RC:
76761 		case DUK_OP_GE_CC:
76762 			DUK__GE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76763 		case DUK_OP_LT_RR:
76764 		case DUK_OP_LT_CR:
76765 		case DUK_OP_LT_RC:
76766 		case DUK_OP_LT_CC:
76767 			DUK__LT_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76768 		case DUK_OP_LE_RR:
76769 		case DUK_OP_LE_CR:
76770 		case DUK_OP_LE_RC:
76771 		case DUK_OP_LE_CC:
76772 			DUK__LE_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
76773 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76774 		case DUK_OP_GT_RR:
76775 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76776 		case DUK_OP_GT_CR:
76777 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76778 		case DUK_OP_GT_RC:
76779 			DUK__GT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76780 		case DUK_OP_GT_CC:
76781 			DUK__GT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76782 		case DUK_OP_GE_RR:
76783 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76784 		case DUK_OP_GE_CR:
76785 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76786 		case DUK_OP_GE_RC:
76787 			DUK__GE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76788 		case DUK_OP_GE_CC:
76789 			DUK__GE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76790 		case DUK_OP_LT_RR:
76791 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76792 		case DUK_OP_LT_CR:
76793 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76794 		case DUK_OP_LT_RC:
76795 			DUK__LT_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76796 		case DUK_OP_LT_CC:
76797 			DUK__LT_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76798 		case DUK_OP_LE_RR:
76799 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
76800 		case DUK_OP_LE_CR:
76801 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
76802 		case DUK_OP_LE_RC:
76803 			DUK__LE_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
76804 		case DUK_OP_LE_CC:
76805 			DUK__LE_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
76806 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76807 
76808 		/* No size optimized variant at present for IF. */
76809 		case DUK_OP_IFTRUE_R: {
76810 			if (duk_js_toboolean(DUK__REGP_BC(ins)) != 0) {
76811 				curr_pc++;
76812 			}
76813 			break;
76814 		}
76815 		case DUK_OP_IFTRUE_C: {
76816 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) != 0) {
76817 				curr_pc++;
76818 			}
76819 			break;
76820 		}
76821 		case DUK_OP_IFFALSE_R: {
76822 			if (duk_js_toboolean(DUK__REGP_BC(ins)) == 0) {
76823 				curr_pc++;
76824 			}
76825 			break;
76826 		}
76827 		case DUK_OP_IFFALSE_C: {
76828 			if (duk_js_toboolean(DUK__CONSTP_BC(ins)) == 0) {
76829 				curr_pc++;
76830 			}
76831 			break;
76832 		}
76833 
76834 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76835 		case DUK_OP_ADD_RR:
76836 		case DUK_OP_ADD_CR:
76837 		case DUK_OP_ADD_RC:
76838 		case DUK_OP_ADD_CC: {
76839 			/* XXX: could leave value on stack top and goto replace_top_a; */
76840 			duk__vm_arith_add(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins));
76841 			break;
76842 		}
76843 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76844 		case DUK_OP_ADD_RR: {
76845 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
76846 			break;
76847 		}
76848 		case DUK_OP_ADD_CR: {
76849 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins));
76850 			break;
76851 		}
76852 		case DUK_OP_ADD_RC: {
76853 			duk__vm_arith_add(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
76854 			break;
76855 		}
76856 		case DUK_OP_ADD_CC: {
76857 			duk__vm_arith_add(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins));
76858 			break;
76859 		}
76860 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76861 
76862 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76863 		case DUK_OP_SUB_RR:
76864 		case DUK_OP_SUB_CR:
76865 		case DUK_OP_SUB_RC:
76866 		case DUK_OP_SUB_CC:
76867 		case DUK_OP_MUL_RR:
76868 		case DUK_OP_MUL_CR:
76869 		case DUK_OP_MUL_RC:
76870 		case DUK_OP_MUL_CC:
76871 		case DUK_OP_DIV_RR:
76872 		case DUK_OP_DIV_CR:
76873 		case DUK_OP_DIV_RC:
76874 		case DUK_OP_DIV_CC:
76875 		case DUK_OP_MOD_RR:
76876 		case DUK_OP_MOD_CR:
76877 		case DUK_OP_MOD_RC:
76878 		case DUK_OP_MOD_CC:
76879 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76880 		case DUK_OP_EXP_RR:
76881 		case DUK_OP_EXP_CR:
76882 		case DUK_OP_EXP_RC:
76883 		case DUK_OP_EXP_CC:
76884 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
76885 		{
76886 			/* XXX: could leave value on stack top and goto replace_top_a; */
76887 			duk__vm_arith_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
76888 			break;
76889 		}
76890 #else  /* DUK_USE_EXEC_PREFER_SIZE */
76891 		case DUK_OP_SUB_RR: {
76892 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76893 			break;
76894 		}
76895 		case DUK_OP_SUB_CR: {
76896 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76897 			break;
76898 		}
76899 		case DUK_OP_SUB_RC: {
76900 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76901 			break;
76902 		}
76903 		case DUK_OP_SUB_CC: {
76904 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_SUB);
76905 			break;
76906 		}
76907 		case DUK_OP_MUL_RR: {
76908 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76909 			break;
76910 		}
76911 		case DUK_OP_MUL_CR: {
76912 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76913 			break;
76914 		}
76915 		case DUK_OP_MUL_RC: {
76916 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76917 			break;
76918 		}
76919 		case DUK_OP_MUL_CC: {
76920 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MUL);
76921 			break;
76922 		}
76923 		case DUK_OP_DIV_RR: {
76924 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76925 			break;
76926 		}
76927 		case DUK_OP_DIV_CR: {
76928 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76929 			break;
76930 		}
76931 		case DUK_OP_DIV_RC: {
76932 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76933 			break;
76934 		}
76935 		case DUK_OP_DIV_CC: {
76936 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_DIV);
76937 			break;
76938 		}
76939 		case DUK_OP_MOD_RR: {
76940 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76941 			break;
76942 		}
76943 		case DUK_OP_MOD_CR: {
76944 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76945 			break;
76946 		}
76947 		case DUK_OP_MOD_RC: {
76948 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76949 			break;
76950 		}
76951 		case DUK_OP_MOD_CC: {
76952 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_MOD);
76953 			break;
76954 		}
76955 #if defined(DUK_USE_ES7_EXP_OPERATOR)
76956 		case DUK_OP_EXP_RR: {
76957 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76958 			break;
76959 		}
76960 		case DUK_OP_EXP_CR: {
76961 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76962 			break;
76963 		}
76964 		case DUK_OP_EXP_RC: {
76965 			duk__vm_arith_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76966 			break;
76967 		}
76968 		case DUK_OP_EXP_CC: {
76969 			duk__vm_arith_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_EXP);
76970 			break;
76971 		}
76972 #endif  /* DUK_USE_ES7_EXP_OPERATOR */
76973 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
76974 
76975 #if defined(DUK_USE_EXEC_PREFER_SIZE)
76976 		case DUK_OP_BAND_RR:
76977 		case DUK_OP_BAND_CR:
76978 		case DUK_OP_BAND_RC:
76979 		case DUK_OP_BAND_CC:
76980 		case DUK_OP_BOR_RR:
76981 		case DUK_OP_BOR_CR:
76982 		case DUK_OP_BOR_RC:
76983 		case DUK_OP_BOR_CC:
76984 		case DUK_OP_BXOR_RR:
76985 		case DUK_OP_BXOR_CR:
76986 		case DUK_OP_BXOR_RC:
76987 		case DUK_OP_BXOR_CC:
76988 		case DUK_OP_BASL_RR:
76989 		case DUK_OP_BASL_CR:
76990 		case DUK_OP_BASL_RC:
76991 		case DUK_OP_BASL_CC:
76992 		case DUK_OP_BLSR_RR:
76993 		case DUK_OP_BLSR_CR:
76994 		case DUK_OP_BLSR_RC:
76995 		case DUK_OP_BLSR_CC:
76996 		case DUK_OP_BASR_RR:
76997 		case DUK_OP_BASR_CR:
76998 		case DUK_OP_BASR_RC:
76999 		case DUK_OP_BASR_CC: {
77000 			/* XXX: could leave value on stack top and goto replace_top_a; */
77001 			duk__vm_bitwise_binary_op(thr, DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins), DUK_DEC_A(ins), op);
77002 			break;
77003 		}
77004 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77005 		case DUK_OP_BAND_RR: {
77006 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77007 			break;
77008 		}
77009 		case DUK_OP_BAND_CR: {
77010 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77011 			break;
77012 		}
77013 		case DUK_OP_BAND_RC: {
77014 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77015 			break;
77016 		}
77017 		case DUK_OP_BAND_CC: {
77018 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BAND);
77019 			break;
77020 		}
77021 		case DUK_OP_BOR_RR: {
77022 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77023 			break;
77024 		}
77025 		case DUK_OP_BOR_CR: {
77026 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77027 			break;
77028 		}
77029 		case DUK_OP_BOR_RC: {
77030 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77031 			break;
77032 		}
77033 		case DUK_OP_BOR_CC: {
77034 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BOR);
77035 			break;
77036 		}
77037 		case DUK_OP_BXOR_RR: {
77038 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77039 			break;
77040 		}
77041 		case DUK_OP_BXOR_CR: {
77042 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77043 			break;
77044 		}
77045 		case DUK_OP_BXOR_RC: {
77046 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77047 			break;
77048 		}
77049 		case DUK_OP_BXOR_CC: {
77050 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BXOR);
77051 			break;
77052 		}
77053 		case DUK_OP_BASL_RR: {
77054 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77055 			break;
77056 		}
77057 		case DUK_OP_BASL_CR: {
77058 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77059 			break;
77060 		}
77061 		case DUK_OP_BASL_RC: {
77062 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77063 			break;
77064 		}
77065 		case DUK_OP_BASL_CC: {
77066 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASL);
77067 			break;
77068 		}
77069 		case DUK_OP_BLSR_RR: {
77070 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77071 			break;
77072 		}
77073 		case DUK_OP_BLSR_CR: {
77074 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77075 			break;
77076 		}
77077 		case DUK_OP_BLSR_RC: {
77078 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77079 			break;
77080 		}
77081 		case DUK_OP_BLSR_CC: {
77082 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BLSR);
77083 			break;
77084 		}
77085 		case DUK_OP_BASR_RR: {
77086 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77087 			break;
77088 		}
77089 		case DUK_OP_BASR_CR: {
77090 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__REGP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77091 			break;
77092 		}
77093 		case DUK_OP_BASR_RC: {
77094 			duk__vm_bitwise_binary_op(thr, DUK__REGP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77095 			break;
77096 		}
77097 		case DUK_OP_BASR_CC: {
77098 			duk__vm_bitwise_binary_op(thr, DUK__CONSTP_B(ins), DUK__CONSTP_C(ins), DUK_DEC_A(ins), DUK_OP_BASR);
77099 			break;
77100 		}
77101 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77102 
77103 		/* For INSTOF and IN, B is always a register. */
77104 #define DUK__INSTOF_BODY(barg,carg) { \
77105 		duk_bool_t tmp; \
77106 		tmp = duk_js_instanceof(thr, (barg), (carg)); \
77107 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77108 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77109 	}
77110 #define DUK__IN_BODY(barg,carg) { \
77111 		duk_bool_t tmp; \
77112 		tmp = duk_js_in(thr, (barg), (carg)); \
77113 		DUK_ASSERT(tmp == 0 || tmp == 1); \
77114 		DUK__REPLACE_BOOL_A_BREAK(tmp); \
77115 	}
77116 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77117 		case DUK_OP_INSTOF_RR:
77118 		case DUK_OP_INSTOF_CR:
77119 		case DUK_OP_INSTOF_RC:
77120 		case DUK_OP_INSTOF_CC:
77121 			DUK__INSTOF_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77122 		case DUK_OP_IN_RR:
77123 		case DUK_OP_IN_CR:
77124 		case DUK_OP_IN_RC:
77125 		case DUK_OP_IN_CC:
77126 			DUK__IN_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77127 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77128 		case DUK_OP_INSTOF_RR:
77129 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77130 		case DUK_OP_INSTOF_CR:
77131 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77132 		case DUK_OP_INSTOF_RC:
77133 			DUK__INSTOF_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77134 		case DUK_OP_INSTOF_CC:
77135 			DUK__INSTOF_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77136 		case DUK_OP_IN_RR:
77137 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77138 		case DUK_OP_IN_CR:
77139 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77140 		case DUK_OP_IN_RC:
77141 			DUK__IN_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77142 		case DUK_OP_IN_CC:
77143 			DUK__IN_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77144 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77145 
77146 		/* Pre/post inc/dec for register variables, important for loops. */
77147 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77148 		case DUK_OP_PREINCR:
77149 		case DUK_OP_PREDECR:
77150 		case DUK_OP_POSTINCR:
77151 		case DUK_OP_POSTDECR: {
77152 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), op);
77153 			break;
77154 		}
77155 		case DUK_OP_PREINCV:
77156 		case DUK_OP_PREDECV:
77157 		case DUK_OP_POSTINCV:
77158 		case DUK_OP_POSTDECV: {
77159 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), op, DUK__STRICT());
77160 			break;
77161 		}
77162 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77163 		case DUK_OP_PREINCR: {
77164 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREINCR);
77165 			break;
77166 		}
77167 		case DUK_OP_PREDECR: {
77168 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_PREDECR);
77169 			break;
77170 		}
77171 		case DUK_OP_POSTINCR: {
77172 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTINCR);
77173 			break;
77174 		}
77175 		case DUK_OP_POSTDECR: {
77176 			duk__prepost_incdec_reg_helper(thr, DUK__REGP_A(ins), DUK__REGP_BC(ins), DUK_OP_POSTDECR);
77177 			break;
77178 		}
77179 		case DUK_OP_PREINCV: {
77180 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREINCV, DUK__STRICT());
77181 			break;
77182 		}
77183 		case DUK_OP_PREDECV: {
77184 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_PREDECV, DUK__STRICT());
77185 			break;
77186 		}
77187 		case DUK_OP_POSTINCV: {
77188 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTINCV, DUK__STRICT());
77189 			break;
77190 		}
77191 		case DUK_OP_POSTDECV: {
77192 			duk__prepost_incdec_var_helper(thr, DUK_DEC_A(ins), DUK__CONSTP_BC(ins), DUK_OP_POSTDECV, DUK__STRICT());
77193 			break;
77194 		}
77195 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77196 
77197 		/* XXX: Move to separate helper, optimize for perf/size separately. */
77198 		/* Preinc/predec for object properties. */
77199 		case DUK_OP_PREINCP_RR:
77200 		case DUK_OP_PREINCP_CR:
77201 		case DUK_OP_PREINCP_RC:
77202 		case DUK_OP_PREINCP_CC:
77203 		case DUK_OP_PREDECP_RR:
77204 		case DUK_OP_PREDECP_CR:
77205 		case DUK_OP_PREDECP_RC:
77206 		case DUK_OP_PREDECP_CC:
77207 		case DUK_OP_POSTINCP_RR:
77208 		case DUK_OP_POSTINCP_CR:
77209 		case DUK_OP_POSTINCP_RC:
77210 		case DUK_OP_POSTINCP_CC:
77211 		case DUK_OP_POSTDECP_RR:
77212 		case DUK_OP_POSTDECP_CR:
77213 		case DUK_OP_POSTDECP_RC:
77214 		case DUK_OP_POSTDECP_CC: {
77215 			duk_tval *tv_obj;
77216 			duk_tval *tv_key;
77217 			duk_tval *tv_val;
77218 			duk_bool_t rc;
77219 			duk_double_t x, y, z;
77220 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
77221 			duk_tval *tv_dst;
77222 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77223 
77224 			/* A -> target reg
77225 			 * B -> object reg/const (may be const e.g. in "'foo'[1]")
77226 			 * C -> key reg/const
77227 			 */
77228 
77229 			/* Opcode bits 0-1 are used to distinguish reg/const variants.
77230 			 * Opcode bits 2-3 are used to distinguish inc/dec variants:
77231 			 * Bit 2 = inc(0)/dec(1), bit 3 = pre(0)/post(1).
77232 			 */
77233 			DUK_ASSERT((DUK_OP_PREINCP_RR & 0x0c) == 0x00);
77234 			DUK_ASSERT((DUK_OP_PREDECP_RR & 0x0c) == 0x04);
77235 			DUK_ASSERT((DUK_OP_POSTINCP_RR & 0x0c) == 0x08);
77236 			DUK_ASSERT((DUK_OP_POSTDECP_RR & 0x0c) == 0x0c);
77237 
77238 			tv_obj = DUK__REGCONSTP_B(ins);
77239 			tv_key = DUK__REGCONSTP_C(ins);
77240 			rc = duk_hobject_getprop(thr, tv_obj, tv_key);  /* -> [val] */
77241 			DUK_UNREF(rc);  /* ignore */
77242 			tv_obj = NULL;  /* invalidated */
77243 			tv_key = NULL;  /* invalidated */
77244 
77245 			/* XXX: Fastint fast path would be useful here.  Also fastints
77246 			 * now lose their fastint status in current handling which is
77247 			 * not intuitive.
77248 			 */
77249 
77250 			x = duk_to_number_m1(thr);
77251 			duk_pop_unsafe(thr);
77252 			if (ins & DUK_BC_INCDECP_FLAG_DEC) {
77253 				y = x - 1.0;
77254 			} else {
77255 				y = x + 1.0;
77256 			}
77257 
77258 			duk_push_number(thr, y);
77259 			tv_val = DUK_GET_TVAL_NEGIDX(thr, -1);
77260 			DUK_ASSERT(tv_val != NULL);
77261 			tv_obj = DUK__REGCONSTP_B(ins);
77262 			tv_key = DUK__REGCONSTP_C(ins);
77263 			rc = duk_hobject_putprop(thr, tv_obj, tv_key, tv_val, DUK__STRICT());
77264 			DUK_UNREF(rc);  /* ignore */
77265 			tv_obj = NULL;  /* invalidated */
77266 			tv_key = NULL;  /* invalidated */
77267 			duk_pop_unsafe(thr);
77268 
77269 			z = (ins & DUK_BC_INCDECP_FLAG_POST) ? x : y;
77270 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77271 			duk_push_number(thr, z);
77272 			DUK__REPLACE_TOP_A_BREAK();
77273 #else
77274 			tv_dst = DUK__REGP_A(ins);
77275 			DUK_TVAL_SET_NUMBER_UPDREF(thr, tv_dst, z);
77276 			break;
77277 #endif
77278 		}
77279 
77280 		/* XXX: GETPROP where object is 'this', GETPROPT?
77281 		 * Occurs relatively often in object oriented code.
77282 		 */
77283 
77284 #define DUK__GETPROP_BODY(barg,carg) { \
77285 		/* A -> target reg \
77286 		 * B -> object reg/const (may be const e.g. in "'foo'[1]") \
77287 		 * C -> key reg/const \
77288 		 */ \
77289 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77290 		DUK__REPLACE_TOP_A_BREAK(); \
77291 	}
77292 #define DUK__GETPROPC_BODY(barg,carg) { \
77293 		/* Same as GETPROP but callability check for property-based calls. */ \
77294 		duk_tval *tv__targ; \
77295 		(void) duk_hobject_getprop(thr, (barg), (carg)); \
77296 		DUK_GC_TORTURE(thr->heap); \
77297 		tv__targ = DUK_GET_TVAL_NEGIDX(thr, -1); \
77298 		if (DUK_UNLIKELY(!duk_is_callable_tval(thr, tv__targ))) { \
77299 			/* Here we intentionally re-evaluate the macro \
77300 			 * arguments to deal with potentially changed \
77301 			 * valstack base pointer! \
77302 			 */ \
77303 			duk_call_setup_propcall_error(thr, tv__targ, (barg), (carg)); \
77304 		} \
77305 		DUK__REPLACE_TOP_A_BREAK(); \
77306 	}
77307 #define DUK__PUTPROP_BODY(aarg,barg,carg) { \
77308 		/* A -> object reg \
77309 		 * B -> key reg/const \
77310 		 * C -> value reg/const \
77311 		 * \
77312 		 * Note: intentional difference to register arrangement \
77313 		 * of e.g. GETPROP; 'A' must contain a register-only value. \
77314 		 */ \
77315 		(void) duk_hobject_putprop(thr, (aarg), (barg), (carg), DUK__STRICT()); \
77316 		break; \
77317 	}
77318 #define DUK__DELPROP_BODY(barg,carg) { \
77319 		/* A -> result reg \
77320 		 * B -> object reg \
77321 		 * C -> key reg/const \
77322 		 */ \
77323 		duk_bool_t rc; \
77324 		rc = duk_hobject_delprop(thr, (barg), (carg), DUK__STRICT()); \
77325 		DUK_ASSERT(rc == 0 || rc == 1); \
77326 		DUK__REPLACE_BOOL_A_BREAK(rc); \
77327 	}
77328 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77329 		case DUK_OP_GETPROP_RR:
77330 		case DUK_OP_GETPROP_CR:
77331 		case DUK_OP_GETPROP_RC:
77332 		case DUK_OP_GETPROP_CC:
77333 			DUK__GETPROP_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77334 #if defined(DUK_USE_VERBOSE_ERRORS)
77335 		case DUK_OP_GETPROPC_RR:
77336 		case DUK_OP_GETPROPC_CR:
77337 		case DUK_OP_GETPROPC_RC:
77338 		case DUK_OP_GETPROPC_CC:
77339 			DUK__GETPROPC_BODY(DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77340 #endif
77341 		case DUK_OP_PUTPROP_RR:
77342 		case DUK_OP_PUTPROP_CR:
77343 		case DUK_OP_PUTPROP_RC:
77344 		case DUK_OP_PUTPROP_CC:
77345 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGCONSTP_B(ins), DUK__REGCONSTP_C(ins));
77346 		case DUK_OP_DELPROP_RR:
77347 		case DUK_OP_DELPROP_RC:  /* B is always reg */
77348 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGCONSTP_C(ins));
77349 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77350 		case DUK_OP_GETPROP_RR:
77351 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77352 		case DUK_OP_GETPROP_CR:
77353 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77354 		case DUK_OP_GETPROP_RC:
77355 			DUK__GETPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77356 		case DUK_OP_GETPROP_CC:
77357 			DUK__GETPROP_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77358 #if defined(DUK_USE_VERBOSE_ERRORS)
77359 		case DUK_OP_GETPROPC_RR:
77360 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77361 		case DUK_OP_GETPROPC_CR:
77362 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77363 		case DUK_OP_GETPROPC_RC:
77364 			DUK__GETPROPC_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77365 		case DUK_OP_GETPROPC_CC:
77366 			DUK__GETPROPC_BODY(DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77367 #endif
77368 		case DUK_OP_PUTPROP_RR:
77369 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__REGP_C(ins));
77370 		case DUK_OP_PUTPROP_CR:
77371 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__REGP_C(ins));
77372 		case DUK_OP_PUTPROP_RC:
77373 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77374 		case DUK_OP_PUTPROP_CC:
77375 			DUK__PUTPROP_BODY(DUK__REGP_A(ins), DUK__CONSTP_B(ins), DUK__CONSTP_C(ins));
77376 		case DUK_OP_DELPROP_RR:  /* B is always reg */
77377 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__REGP_C(ins));
77378 		case DUK_OP_DELPROP_RC:
77379 			DUK__DELPROP_BODY(DUK__REGP_B(ins), DUK__CONSTP_C(ins));
77380 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77381 
77382 		/* No fast path for DECLVAR now, it's quite a rare instruction. */
77383 		case DUK_OP_DECLVAR_RR:
77384 		case DUK_OP_DECLVAR_CR:
77385 		case DUK_OP_DECLVAR_RC:
77386 		case DUK_OP_DECLVAR_CC: {
77387 			duk_activation *act;
77388 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
77389 			duk_tval *tv1;
77390 			duk_hstring *name;
77391 			duk_small_uint_t prop_flags;
77392 			duk_bool_t is_func_decl;
77393 
77394 			tv1 = DUK__REGCONSTP_B(ins);
77395 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77396 			name = DUK_TVAL_GET_STRING(tv1);
77397 			DUK_ASSERT(name != NULL);
77398 
77399 			is_func_decl = ((a & DUK_BC_DECLVAR_FLAG_FUNC_DECL) != 0);
77400 
77401 			/* XXX: declvar takes an duk_tval pointer, which is awkward and
77402 			 * should be reworked.
77403 			 */
77404 
77405 			/* Compiler is responsible for selecting property flags (configurability,
77406 			 * writability, etc).
77407 			 */
77408 			prop_flags = a & DUK_PROPDESC_FLAGS_MASK;
77409 
77410 			if (is_func_decl) {
77411 				duk_push_tval(thr, DUK__REGCONSTP_C(ins));
77412 			} else {
77413 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
77414 				thr->valstack_top++;
77415 			}
77416 			tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
77417 
77418 			act = thr->callstack_curr;
77419 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
77420 				if (is_func_decl) {
77421 					/* Already declared, update value. */
77422 					tv1 = DUK_GET_TVAL_NEGIDX(thr, -1);
77423 					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
77424 				} else {
77425 					/* Already declared but no initializer value
77426 					 * (e.g. 'var xyz;'), no-op.
77427 					 */
77428 				}
77429 			}
77430 
77431 			duk_pop_unsafe(thr);
77432 			break;
77433 		}
77434 
77435 #if defined(DUK_USE_REGEXP_SUPPORT)
77436 		/* The compiler should never emit DUK_OP_REGEXP if there is no
77437 		 * regexp support.
77438 		 */
77439 		case DUK_OP_REGEXP_RR:
77440 		case DUK_OP_REGEXP_CR:
77441 		case DUK_OP_REGEXP_RC:
77442 		case DUK_OP_REGEXP_CC: {
77443 			/* A -> target register
77444 			 * B -> bytecode (also contains flags)
77445 			 * C -> escaped source
77446 			 */
77447 
77448 			duk_push_tval(thr, DUK__REGCONSTP_C(ins));
77449 			duk_push_tval(thr, DUK__REGCONSTP_B(ins));  /* -> [ ... escaped_source bytecode ] */
77450 			duk_regexp_create_instance(thr);   /* -> [ ... regexp_instance ] */
77451 			DUK__REPLACE_TOP_A_BREAK();
77452 		}
77453 #endif  /* DUK_USE_REGEXP_SUPPORT */
77454 
77455 		/* XXX: 'c' is unused, use whole BC, etc. */
77456 		case DUK_OP_CSVAR_RR:
77457 		case DUK_OP_CSVAR_CR:
77458 		case DUK_OP_CSVAR_RC:
77459 		case DUK_OP_CSVAR_CC: {
77460 			/* The speciality of calling through a variable binding is that the
77461 			 * 'this' value may be provided by the variable lookup: E5 Section 6.b.i.
77462 			 *
77463 			 * The only (standard) case where the 'this' binding is non-null is when
77464 			 *   (1) the variable is found in an object environment record, and
77465 			 *   (2) that object environment record is a 'with' block.
77466 			 */
77467 
77468 			duk_activation *act;
77469 			duk_uint_fast_t idx;
77470 			duk_tval *tv1;
77471 			duk_hstring *name;
77472 
77473 			/* A -> target registers (A, A + 1) for call setup
77474 			 * B -> identifier name, usually constant but can be a register due to shuffling
77475 			 */
77476 
77477 			tv1 = DUK__REGCONSTP_B(ins);
77478 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77479 			name = DUK_TVAL_GET_STRING(tv1);
77480 			DUK_ASSERT(name != NULL);
77481 			act = thr->callstack_curr;
77482 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
77483 
77484 			idx = (duk_uint_fast_t) DUK_DEC_A(ins);
77485 
77486 			/* Could add direct value stack handling. */
77487 			duk_replace(thr, (duk_idx_t) (idx + 1));  /* 'this' binding */
77488 			duk_replace(thr, (duk_idx_t) idx);        /* variable value (function, we hope, not checked here) */
77489 			break;
77490 		}
77491 
77492 		case DUK_OP_CLOSURE: {
77493 			duk_activation *act;
77494 			duk_hcompfunc *fun_act;
77495 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77496 			duk_hobject *fun_temp;
77497 
77498 			/* A -> target reg
77499 			 * BC -> inner function index
77500 			 */
77501 
77502 			DUK_DDD(DUK_DDDPRINT("CLOSURE to target register %ld, fnum %ld (count %ld)",
77503 			                     (long) DUK_DEC_A(ins), (long) DUK_DEC_BC(ins), (long) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN())));
77504 
77505 			DUK_ASSERT_DISABLE(bc >= 0); /* unsigned */
77506 			DUK_ASSERT((duk_uint_t) bc < (duk_uint_t) DUK_HCOMPFUNC_GET_FUNCS_COUNT(thr->heap, DUK__FUN()));
77507 
77508 			act = thr->callstack_curr;
77509 			fun_act = (duk_hcompfunc *) DUK_ACT_GET_FUNC(act);
77510 			fun_temp = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, fun_act)[bc];
77511 			DUK_ASSERT(fun_temp != NULL);
77512 			DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC(fun_temp));
77513 
77514 			DUK_DDD(DUK_DDDPRINT("CLOSURE: function template is: %p -> %!O",
77515 			                     (void *) fun_temp, (duk_heaphdr *) fun_temp));
77516 
77517 			if (act->lex_env == NULL) {
77518 				DUK_ASSERT(act->var_env == NULL);
77519 				duk_js_init_activation_environment_records_delayed(thr, act);
77520 				act = thr->callstack_curr;
77521 			}
77522 			DUK_ASSERT(act->lex_env != NULL);
77523 			DUK_ASSERT(act->var_env != NULL);
77524 
77525 			/* functions always have a NEWENV flag, i.e. they get a
77526 			 * new variable declaration environment, so only lex_env
77527 			 * matters here.
77528 			 */
77529 			duk_js_push_closure(thr,
77530 			                    (duk_hcompfunc *) fun_temp,
77531 			                    act->var_env,
77532 			                    act->lex_env,
77533 			                    1 /*add_auto_proto*/);
77534 			DUK__REPLACE_TOP_A_BREAK();
77535 		}
77536 
77537 		case DUK_OP_GETVAR: {
77538 			duk_activation *act;
77539 			duk_tval *tv1;
77540 			duk_hstring *name;
77541 
77542 			tv1 = DUK__CONSTP_BC(ins);
77543 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77544 			name = DUK_TVAL_GET_STRING(tv1);
77545 			DUK_ASSERT(name != NULL);
77546 			act = thr->callstack_curr;
77547 			DUK_ASSERT(act != NULL);
77548 			(void) duk_js_getvar_activation(thr, act, name, 1 /*throw*/);  /* -> [... val this] */
77549 			duk_pop_unsafe(thr);  /* 'this' binding is not needed here */
77550 			DUK__REPLACE_TOP_A_BREAK();
77551 		}
77552 
77553 		case DUK_OP_PUTVAR: {
77554 			duk_activation *act;
77555 			duk_tval *tv1;
77556 			duk_hstring *name;
77557 
77558 			tv1 = DUK__CONSTP_BC(ins);
77559 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77560 			name = DUK_TVAL_GET_STRING(tv1);
77561 			DUK_ASSERT(name != NULL);
77562 
77563 			/* XXX: putvar takes a duk_tval pointer, which is awkward and
77564 			 * should be reworked.
77565 			 */
77566 
77567 			tv1 = DUK__REGP_A(ins);  /* val */
77568 			act = thr->callstack_curr;
77569 			duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
77570 			break;
77571 		}
77572 
77573 		case DUK_OP_DELVAR: {
77574 			duk_activation *act;
77575 			duk_tval *tv1;
77576 			duk_hstring *name;
77577 			duk_bool_t rc;
77578 
77579 			tv1 = DUK__CONSTP_BC(ins);
77580 			DUK_ASSERT(DUK_TVAL_IS_STRING(tv1));
77581 			name = DUK_TVAL_GET_STRING(tv1);
77582 			DUK_ASSERT(name != NULL);
77583 			act = thr->callstack_curr;
77584 			rc = duk_js_delvar_activation(thr, act, name);
77585 			DUK__REPLACE_BOOL_A_BREAK(rc);
77586 		}
77587 
77588 		case DUK_OP_JUMP: {
77589 			/* Note: without explicit cast to signed, MSVC will
77590 			 * apparently generate a large positive jump when the
77591 			 * bias-corrected value would normally be negative.
77592 			 */
77593 			curr_pc += (duk_int_fast_t) DUK_DEC_ABC(ins) - (duk_int_fast_t) DUK_BC_JUMP_BIAS;
77594 			break;
77595 		}
77596 
77597 #define DUK__RETURN_SHARED() do { \
77598 		duk_small_uint_t ret_result; \
77599 		/* duk__handle_return() is guaranteed never to throw, except \
77600 		 * for potential out-of-memory situations which will then \
77601 		 * propagate out of the executor longjmp handler. \
77602 		 */ \
77603 		DUK_ASSERT(thr->ptr_curr_pc == NULL); \
77604 		ret_result = duk__handle_return(thr, entry_act); \
77605 		if (ret_result == DUK__RETHAND_RESTART) { \
77606 			goto restart_execution; \
77607 		} \
77608 		DUK_ASSERT(ret_result == DUK__RETHAND_FINISHED); \
77609 		return; \
77610 	} while (0)
77611 #if defined(DUK_USE_EXEC_PREFER_SIZE)
77612 		case DUK_OP_RETREG:
77613 		case DUK_OP_RETCONST:
77614 		case DUK_OP_RETCONSTN:
77615 		case DUK_OP_RETUNDEF: {
77616 			 /* BC -> return value reg/const */
77617 
77618 			DUK__SYNC_AND_NULL_CURR_PC();
77619 
77620 			if (op == DUK_OP_RETREG) {
77621 				duk_push_tval(thr, DUK__REGP_BC(ins));
77622 			} else if (op == DUK_OP_RETUNDEF) {
77623 				DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));  /* valstack policy */
77624 				thr->valstack_top++;
77625 			} else {
77626 				DUK_ASSERT(op == DUK_OP_RETCONST || op == DUK_OP_RETCONSTN);
77627 				duk_push_tval(thr, DUK__CONSTP_BC(ins));
77628 			}
77629 
77630 			DUK__RETURN_SHARED();
77631 		}
77632 #else  /* DUK_USE_EXEC_PREFER_SIZE */
77633 		case DUK_OP_RETREG: {
77634 			duk_tval *tv;
77635 
77636 			DUK__SYNC_AND_NULL_CURR_PC();
77637 			tv = DUK__REGP_BC(ins);
77638 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77639 			DUK_TVAL_INCREF(thr, tv);
77640 			thr->valstack_top++;
77641 			DUK__RETURN_SHARED();
77642 		}
77643 		/* This will be unused without refcounting. */
77644 		case DUK_OP_RETCONST: {
77645 			duk_tval *tv;
77646 
77647 			DUK__SYNC_AND_NULL_CURR_PC();
77648 			tv = DUK__CONSTP_BC(ins);
77649 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77650 			DUK_TVAL_INCREF(thr, tv);
77651 			thr->valstack_top++;
77652 			DUK__RETURN_SHARED();
77653 		}
77654 		case DUK_OP_RETCONSTN: {
77655 			duk_tval *tv;
77656 
77657 			DUK__SYNC_AND_NULL_CURR_PC();
77658 			tv = DUK__CONSTP_BC(ins);
77659 			DUK_TVAL_SET_TVAL(thr->valstack_top, tv);
77660 #if defined(DUK_USE_REFERENCE_COUNTING)
77661 			/* Without refcounting only RETCONSTN is used. */
77662 			DUK_ASSERT(!DUK_TVAL_IS_HEAP_ALLOCATED(tv));  /* no INCREF for this constant */
77663 #endif
77664 			thr->valstack_top++;
77665 			DUK__RETURN_SHARED();
77666 		}
77667 		case DUK_OP_RETUNDEF: {
77668 			DUK__SYNC_AND_NULL_CURR_PC();
77669 			thr->valstack_top++;  /* value at valstack top is already undefined by valstack policy */
77670 			DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(thr->valstack_top));
77671 			DUK__RETURN_SHARED();
77672 		}
77673 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
77674 
77675 		case DUK_OP_LABEL: {
77676 			duk_activation *act;
77677 			duk_catcher *cat;
77678 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77679 
77680 			/* Allocate catcher and populate it (must be atomic). */
77681 
77682 			cat = duk_hthread_catcher_alloc(thr);
77683 			DUK_ASSERT(cat != NULL);
77684 
77685 			cat->flags = (duk_uint32_t) (DUK_CAT_TYPE_LABEL | (bc << DUK_CAT_LABEL_SHIFT));
77686 			cat->pc_base = (duk_instr_t *) curr_pc;  /* pre-incremented, points to first jump slot */
77687 			cat->idx_base = 0;  /* unused for label */
77688 			cat->h_varname = NULL;
77689 
77690 			act = thr->callstack_curr;
77691 			DUK_ASSERT(act != NULL);
77692 			cat->parent = act->cat;
77693 			act->cat = cat;
77694 
77695 			DUK_DDD(DUK_DDDPRINT("LABEL catcher: flags=0x%08lx, pc_base=%ld, "
77696 			                     "idx_base=%ld, h_varname=%!O, label_id=%ld",
77697 			                     (long) cat->flags, (long) cat->pc_base,
77698 			                     (long) cat->idx_base, (duk_heaphdr *) cat->h_varname, (long) DUK_CAT_GET_LABEL(cat)));
77699 
77700 			curr_pc += 2;  /* skip jump slots */
77701 			break;
77702 		}
77703 
77704 		case DUK_OP_ENDLABEL: {
77705 			duk_activation *act;
77706 #if (defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)) || defined(DUK_USE_ASSERTIONS)
77707 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77708 #endif
77709 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
77710 			DUK_DDD(DUK_DDDPRINT("ENDLABEL %ld", (long) bc));
77711 #endif
77712 
77713 			act = thr->callstack_curr;
77714 			DUK_ASSERT(act->cat != NULL);
77715 			DUK_ASSERT(DUK_CAT_GET_TYPE(act->cat) == DUK_CAT_TYPE_LABEL);
77716 			DUK_ASSERT((duk_uint_fast_t) DUK_CAT_GET_LABEL(act->cat) == bc);
77717 			duk_hthread_catcher_unwind_nolexenv_norz(thr, act);
77718 
77719 			/* no need to unwind callstack */
77720 			break;
77721 		}
77722 
77723 		case DUK_OP_BREAK: {
77724 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77725 
77726 			DUK__SYNC_AND_NULL_CURR_PC();
77727 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_BREAK);
77728 			goto restart_execution;
77729 		}
77730 
77731 		case DUK_OP_CONTINUE: {
77732 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77733 
77734 			DUK__SYNC_AND_NULL_CURR_PC();
77735 			duk__handle_break_or_continue(thr, (duk_uint_t) bc, DUK_LJ_TYPE_CONTINUE);
77736 			goto restart_execution;
77737 		}
77738 
77739 		/* XXX: move to helper, too large to be inline here */
77740 		case DUK_OP_TRYCATCH: {
77741 			duk__handle_op_trycatch(thr, ins, curr_pc);
77742 			curr_pc += 2;  /* skip jump slots */
77743 			break;
77744 		}
77745 
77746 		case DUK_OP_ENDTRY: {
77747 			curr_pc = duk__handle_op_endtry(thr, ins);
77748 			break;
77749 		}
77750 
77751 		case DUK_OP_ENDCATCH: {
77752 			duk__handle_op_endcatch(thr, ins);
77753 			break;
77754 		}
77755 
77756 		case DUK_OP_ENDFIN: {
77757 			/* Sync and NULL early. */
77758 			DUK__SYNC_AND_NULL_CURR_PC();
77759 
77760 			if (duk__handle_op_endfin(thr, ins, entry_act) != 0) {
77761 				return;
77762 			}
77763 
77764 			/* Must restart because we NULLed out curr_pc. */
77765 			goto restart_execution;
77766 		}
77767 
77768 		case DUK_OP_THROW: {
77769 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77770 
77771 			/* Note: errors are augmented when they are created, not
77772 			 * when they are thrown.  So, don't augment here, it would
77773 			 * break re-throwing for instance.
77774 			 */
77775 
77776 			/* Sync so that augmentation sees up-to-date activations, NULL
77777 			 * thr->ptr_curr_pc so that it's not used if side effects occur
77778 			 * in augmentation or longjmp handling.
77779 			 */
77780 			DUK__SYNC_AND_NULL_CURR_PC();
77781 
77782 			duk_dup(thr, (duk_idx_t) bc);
77783 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (before throw augment)",
77784 			                     (duk_tval *) duk_get_tval(thr, -1)));
77785 #if defined(DUK_USE_AUGMENT_ERROR_THROW)
77786 			duk_err_augment_error_throw(thr);
77787 			DUK_DDD(DUK_DDDPRINT("THROW ERROR (BYTECODE): %!dT (after throw augment)",
77788 			                     (duk_tval *) duk_get_tval(thr, -1)));
77789 #endif
77790 
77791 			duk_err_setup_ljstate1(thr, DUK_LJ_TYPE_THROW, DUK_GET_TVAL_NEGIDX(thr, -1));
77792 #if defined(DUK_USE_DEBUGGER_SUPPORT)
77793 			duk_err_check_debugger_integration(thr);
77794 #endif
77795 
77796 			DUK_ASSERT(thr->heap->lj.jmpbuf_ptr != NULL);  /* always in executor */
77797 			duk_err_longjmp(thr);
77798 			DUK_UNREACHABLE();
77799 			break;
77800 		}
77801 
77802 		case DUK_OP_CSREG: {
77803 			/*
77804 			 *  Assuming a register binds to a variable declared within this
77805 			 *  function (a declarative binding), the 'this' for the call
77806 			 *  setup is always 'undefined'.  E5 Section 10.2.1.1.6.
77807 			 */
77808 
77809 			duk_small_uint_fast_t a = DUK_DEC_A(ins);
77810 			duk_small_uint_fast_t bc = DUK_DEC_BC(ins);
77811 
77812 			/* A -> register containing target function (not type checked here)
77813 			 * BC -> target registers (BC, BC + 1) for call setup
77814 			 */
77815 
77816 #if defined(DUK_USE_PREFER_SIZE)
77817 			duk_dup(thr, (duk_idx_t) a);
77818 			duk_replace(thr, (duk_idx_t) bc);
77819 			duk_to_undefined(thr, (duk_idx_t) (bc + 1));
77820 #else
77821 			duk_tval *tv1;
77822 			duk_tval *tv2;
77823 			duk_tval *tv3;
77824 			duk_tval tv_tmp1;
77825 			duk_tval tv_tmp2;
77826 
77827 			tv1 = DUK__REGP(bc);
77828 			tv2 = tv1 + 1;
77829 			DUK_TVAL_SET_TVAL(&tv_tmp1, tv1);
77830 			DUK_TVAL_SET_TVAL(&tv_tmp2, tv2);
77831 			tv3 = DUK__REGP(a);
77832 			DUK_TVAL_SET_TVAL(tv1, tv3);
77833 			DUK_TVAL_INCREF(thr, tv1);  /* no side effects */
77834 			DUK_TVAL_SET_UNDEFINED(tv2);  /* no need for incref */
77835 			DUK_TVAL_DECREF(thr, &tv_tmp1);
77836 			DUK_TVAL_DECREF(thr, &tv_tmp2);
77837 #endif
77838 			break;
77839 		}
77840 
77841 
77842 		/* XXX: in some cases it's faster NOT to reuse the value
77843 		 * stack but rather copy the arguments on top of the stack
77844 		 * (mainly when the calling value stack is large and the value
77845 		 * stack resize would be large).
77846 		 */
77847 
77848 		case DUK_OP_CALL0:
77849 		case DUK_OP_CALL1:
77850 		case DUK_OP_CALL2:
77851 		case DUK_OP_CALL3:
77852 		case DUK_OP_CALL4:
77853 		case DUK_OP_CALL5:
77854 		case DUK_OP_CALL6:
77855 		case DUK_OP_CALL7: {
77856 			/* Opcode packs 4 flag bits: 1 for indirect, 3 map
77857 			 * 1:1 to three lowest call handling flags.
77858 			 *
77859 			 * A -> nargs or register with nargs (indirect)
77860 			 * BC -> base register for call (base -> func, base+1 -> this, base+2 -> arg1 ... base+2+N-1 -> argN)
77861 			 */
77862 
77863 			duk_idx_t nargs;
77864 			duk_idx_t idx;
77865 			duk_small_uint_t call_flags;
77866 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77867 			duk_hcompfunc *fun;
77868 #endif
77869 
77870 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
77871 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) == 0);
77872 
77873 			nargs = (duk_idx_t) DUK_DEC_A(ins);
77874 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
77875 			idx = (duk_idx_t) DUK_DEC_BC(ins);
77876 
77877 			if (duk__executor_handle_call(thr, idx, nargs, call_flags)) {
77878 				/* curr_pc synced by duk_handle_call_unprotected() */
77879 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
77880 				goto restart_execution;
77881 			}
77882 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
77883 
77884 			/* duk_js_call.c is required to restore the stack reserve
77885 			 * so we only need to reset the top.
77886 			 */
77887 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77888 			fun = DUK__FUN();
77889 #endif
77890 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
77891 
77892 			/* No need to reinit setjmp() catchpoint, as call handling
77893 			 * will store and restore our state.
77894 			 *
77895 			 * When debugger is enabled, we need to recheck the activation
77896 			 * status after returning.  This is now handled by call handling
77897 			 * and heap->dbg_force_restart.
77898 			 */
77899 			break;
77900 		}
77901 
77902 		case DUK_OP_CALL8:
77903 		case DUK_OP_CALL9:
77904 		case DUK_OP_CALL10:
77905 		case DUK_OP_CALL11:
77906 		case DUK_OP_CALL12:
77907 		case DUK_OP_CALL13:
77908 		case DUK_OP_CALL14:
77909 		case DUK_OP_CALL15: {
77910 			/* Indirect variant. */
77911 			duk_uint_fast_t nargs;
77912 			duk_idx_t idx;
77913 			duk_small_uint_t call_flags;
77914 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77915 			duk_hcompfunc *fun;
77916 #endif
77917 
77918 			DUK_ASSERT((DUK_OP_CALL0 & 0x0fU) == 0);
77919 			DUK_ASSERT((ins & DUK_BC_CALL_FLAG_INDIRECT) != 0);
77920 
77921 			nargs = (duk_uint_fast_t) DUK_DEC_A(ins);
77922 			DUK__LOOKUP_INDIRECT(nargs);
77923 			call_flags = (ins & 0x07U) | DUK_CALL_FLAG_ALLOW_ECMATOECMA;
77924 			idx = (duk_idx_t) DUK_DEC_BC(ins);
77925 
77926 			if (duk__executor_handle_call(thr, idx, (duk_idx_t) nargs, call_flags)) {
77927 				DUK_ASSERT(thr->ptr_curr_pc == NULL);
77928 				goto restart_execution;
77929 			}
77930 			DUK_ASSERT(thr->ptr_curr_pc != NULL);
77931 
77932 #if !defined(DUK_USE_EXEC_FUN_LOCAL)
77933 			fun = DUK__FUN();
77934 #endif
77935 			duk_set_top_unsafe(thr, (duk_idx_t) fun->nregs);
77936 			break;
77937 		}
77938 
77939 		case DUK_OP_NEWOBJ: {
77940 			duk_push_object(thr);
77941 #if defined(DUK_USE_ASSERTIONS)
77942 			{
77943 				duk_hobject *h;
77944 				h = duk_require_hobject(thr, -1);
77945 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
77946 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
77947 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
77948 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
77949 			}
77950 #endif
77951 #if !defined(DUK_USE_PREFER_SIZE)
77952 			/* XXX: could do a direct props realloc, but need hash size */
77953 			duk_hobject_resize_entrypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
77954 #endif
77955 			DUK__REPLACE_TOP_BC_BREAK();
77956 		}
77957 
77958 		case DUK_OP_NEWARR: {
77959 			duk_push_array(thr);
77960 #if defined(DUK_USE_ASSERTIONS)
77961 			{
77962 				duk_hobject *h;
77963 				h = duk_require_hobject(thr, -1);
77964 				DUK_ASSERT(DUK_HOBJECT_GET_ESIZE(h) == 0);
77965 				DUK_ASSERT(DUK_HOBJECT_GET_ENEXT(h) == 0);
77966 				DUK_ASSERT(DUK_HOBJECT_GET_ASIZE(h) == 0);
77967 				DUK_ASSERT(DUK_HOBJECT_GET_HSIZE(h) == 0);
77968 				DUK_ASSERT(DUK_HOBJECT_HAS_ARRAY_PART(h));
77969 			}
77970 #endif
77971 #if !defined(DUK_USE_PREFER_SIZE)
77972 			duk_hobject_realloc_props(thr,
77973 			                          duk_known_hobject(thr, -1),
77974 			                          0 /*new_e_size*/,
77975 			                          DUK_DEC_A(ins) /*new_a_size*/,
77976 			                          0 /*new_h_size*/,
77977 			                          0 /*abandon_array*/);
77978 #if 0
77979 			duk_hobject_resize_arraypart(thr, duk_known_hobject(thr, -1), DUK_DEC_A(ins));
77980 #endif
77981 #endif
77982 			DUK__REPLACE_TOP_BC_BREAK();
77983 		}
77984 
77985 		case DUK_OP_MPUTOBJ:
77986 		case DUK_OP_MPUTOBJI: {
77987 			duk_idx_t obj_idx;
77988 			duk_uint_fast_t idx, idx_end;
77989 			duk_small_uint_fast_t count;
77990 
77991 			/* A -> register of target object
77992 			 * B -> first register of key/value pair list
77993 			 *      or register containing first register number if indirect
77994 			 * C -> number of key/value pairs * 2
77995 			 *      (= number of value stack indices used starting from 'B')
77996 			 */
77997 
77998 			obj_idx = DUK_DEC_A(ins);
77999 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78000 
78001 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78002 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTOBJI) {
78003 				DUK__LOOKUP_INDIRECT(idx);
78004 			}
78005 
78006 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78007 			DUK_ASSERT(count > 0);  /* compiler guarantees */
78008 			idx_end = idx + count;
78009 
78010 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78011 			if (DUK_UNLIKELY(idx_end > (duk_uint_fast_t) duk_get_top(thr))) {
78012 				/* XXX: use duk_is_valid_index() instead? */
78013 				/* XXX: improve check; check against nregs, not against top */
78014 				DUK__INTERNAL_ERROR("MPUTOBJ out of bounds");
78015 			}
78016 #endif
78017 
78018 			/* Use 'force' flag to duk_def_prop() to ensure that any
78019 			 * inherited properties don't prevent the operation.
78020 			 * With ES2015 duplicate properties are allowed, so that we
78021 			 * must overwrite any previous data or accessor property.
78022 			 *
78023 			 * With ES2015 computed property names the literal keys
78024 			 * may be arbitrary values and need to be ToPropertyKey()
78025 			 * coerced at runtime.
78026 			 */
78027 			do {
78028 				/* XXX: faster initialization (direct access or better primitives) */
78029 				duk_dup(thr, (duk_idx_t) idx);
78030 				duk_dup(thr, (duk_idx_t) (idx + 1));
78031 				duk_def_prop(thr, obj_idx, DUK_DEFPROP_HAVE_VALUE |
78032 				                           DUK_DEFPROP_FORCE |
78033 				                           DUK_DEFPROP_SET_WRITABLE |
78034 				                           DUK_DEFPROP_SET_ENUMERABLE |
78035 				                           DUK_DEFPROP_SET_CONFIGURABLE);
78036 				idx += 2;
78037 			} while (idx < idx_end);
78038 			break;
78039 		}
78040 
78041 		case DUK_OP_INITSET:
78042 		case DUK_OP_INITGET: {
78043 			duk__handle_op_initset_initget(thr, ins);
78044 			break;
78045 		}
78046 
78047 		case DUK_OP_MPUTARR:
78048 		case DUK_OP_MPUTARRI: {
78049 			duk_idx_t obj_idx;
78050 			duk_uint_fast_t idx, idx_end;
78051 			duk_small_uint_fast_t count;
78052 			duk_tval *tv1;
78053 			duk_uint32_t arr_idx;
78054 
78055 			/* A -> register of target object
78056 			 * B -> first register of value data (start_index, value1, value2, ..., valueN)
78057 			 *      or register containing first register number if indirect
78058 			 * C -> number of key/value pairs (N)
78059 			 */
78060 
78061 			obj_idx = DUK_DEC_A(ins);
78062 			DUK_ASSERT(duk_is_object(thr, obj_idx));
78063 
78064 			idx = (duk_uint_fast_t) DUK_DEC_B(ins);
78065 			if (DUK_DEC_OP(ins) == DUK_OP_MPUTARRI) {
78066 				DUK__LOOKUP_INDIRECT(idx);
78067 			}
78068 
78069 			count = (duk_small_uint_fast_t) DUK_DEC_C(ins);
78070 			DUK_ASSERT(count > 0 + 1);  /* compiler guarantees */
78071 			idx_end = idx + count;
78072 
78073 #if defined(DUK_USE_EXEC_INDIRECT_BOUND_CHECK)
78074 			if (idx_end > (duk_uint_fast_t) duk_get_top(thr)) {
78075 				/* XXX: use duk_is_valid_index() instead? */
78076 				/* XXX: improve check; check against nregs, not against top */
78077 				DUK__INTERNAL_ERROR("MPUTARR out of bounds");
78078 			}
78079 #endif
78080 
78081 			tv1 = DUK__REGP(idx);
78082 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78083 #if defined(DUK_USE_FASTINT)
78084 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78085 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78086 #else
78087 			arr_idx = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78088 #endif
78089 			idx++;
78090 
78091 			do {
78092 				/* duk_xdef_prop() will define an own property without any array
78093 				 * special behaviors.  We'll need to set the array length explicitly
78094 				 * in the end.  For arrays with elisions, the compiler will emit an
78095 				 * explicit SETALEN which will update the length.
78096 				 */
78097 
78098 				/* XXX: because we're dealing with 'own' properties of a fresh array,
78099 				 * the array initializer should just ensure that the array has a large
78100 				 * enough array part and write the values directly into array part,
78101 				 * and finally set 'length' manually in the end (as already happens now).
78102 				 */
78103 
78104 				duk_dup(thr, (duk_idx_t) idx);
78105 				duk_xdef_prop_index_wec(thr, obj_idx, arr_idx);
78106 
78107 				idx++;
78108 				arr_idx++;
78109 			} while (idx < idx_end);
78110 
78111 			/* XXX: E5.1 Section 11.1.4 coerces the final length through
78112 			 * ToUint32() which is odd but happens now as a side effect of
78113 			 * 'arr_idx' type.
78114 			 */
78115 			duk_set_length(thr, obj_idx, (duk_size_t) (duk_uarridx_t) arr_idx);
78116 			break;
78117 		}
78118 
78119 		case DUK_OP_SETALEN: {
78120 			duk_tval *tv1;
78121 			duk_hobject *h;
78122 			duk_uint32_t len;
78123 
78124 			tv1 = DUK__REGP_A(ins);
78125 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv1));
78126 			h = DUK_TVAL_GET_OBJECT(tv1);
78127 			DUK_ASSERT(DUK_HOBJECT_IS_ARRAY(h));
78128 
78129 			tv1 = DUK__REGP_BC(ins);
78130 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv1));
78131 #if defined(DUK_USE_FASTINT)
78132 			DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv1));
78133 			len = (duk_uint32_t) DUK_TVAL_GET_FASTINT_U32(tv1);
78134 #else
78135 			len = (duk_uint32_t) DUK_TVAL_GET_NUMBER(tv1);
78136 #endif
78137 			((duk_harray *) h)->length = len;
78138 			break;
78139 		}
78140 
78141 		case DUK_OP_INITENUM: {
78142 			duk__handle_op_initenum(thr, ins);
78143 			break;
78144 		}
78145 
78146 		case DUK_OP_NEXTENUM: {
78147 			curr_pc += duk__handle_op_nextenum(thr, ins);
78148 			break;
78149 		}
78150 
78151 		case DUK_OP_INVLHS: {
78152 			DUK_ERROR_REFERENCE(thr, DUK_STR_INVALID_LVALUE);
78153 			DUK_WO_NORETURN(return;);
78154 			break;
78155 		}
78156 
78157 		case DUK_OP_DEBUGGER: {
78158 			/* Opcode only emitted by compiler when debugger
78159 			 * support is enabled.  Ignore it silently without
78160 			 * debugger support, in case it has been loaded
78161 			 * from precompiled bytecode.
78162 			 */
78163 #if defined(DUK_USE_DEBUGGER_SUPPORT)
78164 			if (duk_debug_is_attached(thr->heap)) {
78165 				DUK_D(DUK_DPRINT("DEBUGGER statement encountered, halt execution"));
78166 				DUK__SYNC_AND_NULL_CURR_PC();
78167 				duk_debug_halt_execution(thr, 1 /*use_prev_pc*/);
78168 				DUK_D(DUK_DPRINT("DEBUGGER statement finished, resume execution"));
78169 				goto restart_execution;
78170 			} else {
78171 				DUK_D(DUK_DPRINT("DEBUGGER statement ignored, debugger not attached"));
78172 			}
78173 #else
78174 			DUK_D(DUK_DPRINT("DEBUGGER statement ignored, no debugger support"));
78175 #endif
78176 			break;
78177 		}
78178 
78179 		case DUK_OP_NOP: {
78180 			/* Nop, ignored, but ABC fields may carry a value e.g.
78181 			 * for indirect opcode handling.
78182 			 */
78183 			break;
78184 		}
78185 
78186 		case DUK_OP_INVALID: {
78187 			DUK_ERROR_FMT1(thr, DUK_ERR_ERROR, "INVALID opcode (%ld)", (long) DUK_DEC_ABC(ins));
78188 			DUK_WO_NORETURN(return;);
78189 			break;
78190 		}
78191 
78192 #if defined(DUK_USE_ES6)
78193 		case DUK_OP_NEWTARGET: {
78194 			duk_push_new_target(thr);
78195 			DUK__REPLACE_TOP_BC_BREAK();
78196 		}
78197 #endif  /* DUK_USE_ES6 */
78198 
78199 #if !defined(DUK_USE_EXEC_PREFER_SIZE)
78200 #if !defined(DUK_USE_ES7_EXP_OPERATOR)
78201 		case DUK_OP_EXP_RR:
78202 		case DUK_OP_EXP_CR:
78203 		case DUK_OP_EXP_RC:
78204 		case DUK_OP_EXP_CC:
78205 #endif
78206 #if !defined(DUK_USE_ES6)
78207 		case DUK_OP_NEWTARGET:
78208 #endif
78209 #if !defined(DUK_USE_VERBOSE_ERRORS)
78210 		case DUK_OP_GETPROPC_RR:
78211 		case DUK_OP_GETPROPC_CR:
78212 		case DUK_OP_GETPROPC_RC:
78213 		case DUK_OP_GETPROPC_CC:
78214 #endif
78215 		case DUK_OP_UNUSED207:
78216 		case DUK_OP_UNUSED212:
78217 		case DUK_OP_UNUSED213:
78218 		case DUK_OP_UNUSED214:
78219 		case DUK_OP_UNUSED215:
78220 		case DUK_OP_UNUSED216:
78221 		case DUK_OP_UNUSED217:
78222 		case DUK_OP_UNUSED218:
78223 		case DUK_OP_UNUSED219:
78224 		case DUK_OP_UNUSED220:
78225 		case DUK_OP_UNUSED221:
78226 		case DUK_OP_UNUSED222:
78227 		case DUK_OP_UNUSED223:
78228 		case DUK_OP_UNUSED224:
78229 		case DUK_OP_UNUSED225:
78230 		case DUK_OP_UNUSED226:
78231 		case DUK_OP_UNUSED227:
78232 		case DUK_OP_UNUSED228:
78233 		case DUK_OP_UNUSED229:
78234 		case DUK_OP_UNUSED230:
78235 		case DUK_OP_UNUSED231:
78236 		case DUK_OP_UNUSED232:
78237 		case DUK_OP_UNUSED233:
78238 		case DUK_OP_UNUSED234:
78239 		case DUK_OP_UNUSED235:
78240 		case DUK_OP_UNUSED236:
78241 		case DUK_OP_UNUSED237:
78242 		case DUK_OP_UNUSED238:
78243 		case DUK_OP_UNUSED239:
78244 		case DUK_OP_UNUSED240:
78245 		case DUK_OP_UNUSED241:
78246 		case DUK_OP_UNUSED242:
78247 		case DUK_OP_UNUSED243:
78248 		case DUK_OP_UNUSED244:
78249 		case DUK_OP_UNUSED245:
78250 		case DUK_OP_UNUSED246:
78251 		case DUK_OP_UNUSED247:
78252 		case DUK_OP_UNUSED248:
78253 		case DUK_OP_UNUSED249:
78254 		case DUK_OP_UNUSED250:
78255 		case DUK_OP_UNUSED251:
78256 		case DUK_OP_UNUSED252:
78257 		case DUK_OP_UNUSED253:
78258 		case DUK_OP_UNUSED254:
78259 		case DUK_OP_UNUSED255:
78260 		/* Force all case clauses to map to an actual handler
78261 		 * so that the compiler can emit a jump without a bounds
78262 		 * check: the switch argument is a duk_uint8_t so that
78263 		 * the compiler may be able to figure it out.  This is
78264 		 * a small detail and obviously compiler dependent.
78265 		 */
78266 		/* default: clause omitted on purpose */
78267 #else  /* DUK_USE_EXEC_PREFER_SIZE */
78268 		default:
78269 #endif  /* DUK_USE_EXEC_PREFER_SIZE */
78270 		{
78271 			/* Default case catches invalid/unsupported opcodes. */
78272 			DUK_D(DUK_DPRINT("invalid opcode: %ld - %!I", (long) op, ins));
78273 			DUK__INTERNAL_ERROR("invalid opcode");
78274 			break;
78275 		}
78276 
78277 		}  /* end switch */
78278 
78279 		continue;
78280 
78281 		/* Some shared exit paths for opcode handling below.  These
78282 		 * are mostly useful to reduce code footprint when multiple
78283 		 * opcodes have a similar epilogue (like replacing stack top
78284 		 * with index 'a').
78285 		 */
78286 
78287 #if defined(DUK_USE_EXEC_PREFER_SIZE)
78288 	 replace_top_a:
78289 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_A(ins));
78290 		continue;
78291 	 replace_top_bc:
78292 		DUK__REPLACE_TO_TVPTR(thr, DUK__REGP_BC(ins));
78293 		continue;
78294 #endif
78295 	}
78296 	DUK_WO_NORETURN(return;);
78297 
78298 #if !defined(DUK_USE_VERBOSE_EXECUTOR_ERRORS)
78299  internal_error:
78300 	DUK_ERROR_INTERNAL(thr);
78301 	DUK_WO_NORETURN(return;);
78302 #endif
78303 }
78304 
78305 /* automatic undefs */
78306 #undef DUK__BYTEOFF_A
78307 #undef DUK__BYTEOFF_B
78308 #undef DUK__BYTEOFF_BC
78309 #undef DUK__BYTEOFF_C
78310 #undef DUK__COMPARE_BODY
78311 #undef DUK__CONST
78312 #undef DUK__CONSTP
78313 #undef DUK__CONSTP_A
78314 #undef DUK__CONSTP_B
78315 #undef DUK__CONSTP_BC
78316 #undef DUK__CONSTP_C
78317 #undef DUK__DELPROP_BODY
78318 #undef DUK__EQ_BODY
78319 #undef DUK__FUN
78320 #undef DUK__GETPROPC_BODY
78321 #undef DUK__GETPROP_BODY
78322 #undef DUK__GE_BODY
78323 #undef DUK__GT_BODY
78324 #undef DUK__INLINE_PERF
78325 #undef DUK__INSTOF_BODY
78326 #undef DUK__INTERNAL_ERROR
78327 #undef DUK__INT_NOACTION
78328 #undef DUK__INT_RESTART
78329 #undef DUK__IN_BODY
78330 #undef DUK__LE_BODY
78331 #undef DUK__LONGJMP_RESTART
78332 #undef DUK__LONGJMP_RETHROW
78333 #undef DUK__LOOKUP_INDIRECT
78334 #undef DUK__LT_BODY
78335 #undef DUK__MASK_A
78336 #undef DUK__MASK_B
78337 #undef DUK__MASK_BC
78338 #undef DUK__MASK_C
78339 #undef DUK__NEQ_BODY
78340 #undef DUK__NOINLINE_PERF
78341 #undef DUK__PUTPROP_BODY
78342 #undef DUK__RCBIT_B
78343 #undef DUK__RCBIT_C
78344 #undef DUK__REG
78345 #undef DUK__REGCONSTP_B
78346 #undef DUK__REGCONSTP_C
78347 #undef DUK__REGP
78348 #undef DUK__REGP_A
78349 #undef DUK__REGP_B
78350 #undef DUK__REGP_BC
78351 #undef DUK__REGP_C
78352 #undef DUK__REPLACE_BOOL_A_BREAK
78353 #undef DUK__REPLACE_TOP_A_BREAK
78354 #undef DUK__REPLACE_TOP_BC_BREAK
78355 #undef DUK__REPLACE_TO_TVPTR
78356 #undef DUK__RETHAND_FINISHED
78357 #undef DUK__RETHAND_RESTART
78358 #undef DUK__RETURN_SHARED
78359 #undef DUK__SEQ_BODY
78360 #undef DUK__SHIFT_A
78361 #undef DUK__SHIFT_B
78362 #undef DUK__SHIFT_BC
78363 #undef DUK__SHIFT_C
78364 #undef DUK__SNEQ_BODY
78365 #undef DUK__STRICT
78366 #undef DUK__SYNC_AND_NULL_CURR_PC
78367 #undef DUK__SYNC_CURR_PC
78368 #undef DUK__TVAL_SHIFT
78369 #line 1 "duk_js_ops.c"
78370 /*
78371  *  ECMAScript specification algorithm and conversion helpers.
78372  *
78373  *  These helpers encapsulate the primitive ECMAScript operation semantics,
78374  *  and are used by the bytecode executor and the API (among other places).
78375  *  Some primitives are only implemented as part of the API and have no
78376  *  "internal" helper.  This is the case when an internal helper would not
78377  *  really be useful; e.g. the operation is rare, uses value stack heavily,
78378  *  etc.
78379  *
78380  *  The operation arguments depend on what is required to implement
78381  *  the operation:
78382  *
78383  *    - If an operation is simple and stateless, and has no side
78384  *      effects, it won't take an duk_hthread argument and its
78385  *      arguments may be duk_tval pointers (which are safe as long
78386  *      as no side effects take place).
78387  *
78388  *    - If complex coercions are required (e.g. a "ToNumber" coercion)
78389  *      or errors may be thrown, the operation takes an duk_hthread
78390  *      argument.  This also implies that the operation may have
78391  *      arbitrary side effects, invalidating any duk_tval pointers.
78392  *
78393  *    - For operations with potential side effects, arguments can be
78394  *      taken in several ways:
78395  *
78396  *      a) as duk_tval pointers, which makes sense if the "common case"
78397  *         can be resolved without side effects (e.g. coercion); the
78398  *         arguments are pushed to the valstack for coercion if
78399  *         necessary
78400  *
78401  *      b) as duk_tval values
78402  *
78403  *      c) implicitly on value stack top
78404  *
78405  *      d) as indices to the value stack
78406  *
78407  *  Future work:
78408  *
78409  *     - Argument styles may not be the most sensible in every case now.
78410  *
78411  *     - In-place coercions might be useful for several operations, if
78412  *       in-place coercion is OK for the bytecode executor and the API.
78413  */
78414 
78415 /* #include duk_internal.h -> already included */
78416 
78417 /*
78418  *  ToPrimitive()  (E5 Section 9.1)
78419  *
78420  *  ==> implemented in the API.
78421  */
78422 
78423 /*
78424  *  ToBoolean()  (E5 Section 9.2)
78425  */
78426 
78427 DUK_INTERNAL duk_bool_t duk_js_toboolean(duk_tval *tv) {
78428 	switch (DUK_TVAL_GET_TAG(tv)) {
78429 	case DUK_TAG_UNDEFINED:
78430 	case DUK_TAG_NULL:
78431 		return 0;
78432 	case DUK_TAG_BOOLEAN:
78433 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv) == 0 || DUK_TVAL_GET_BOOLEAN(tv) == 1);
78434 		return DUK_TVAL_GET_BOOLEAN(tv);
78435 	case DUK_TAG_STRING: {
78436 		/* Symbols ToBoolean() coerce to true, regardless of their
78437 		 * description.  This happens with no explicit check because
78438 		 * of the symbol representation byte prefix.
78439 		 */
78440 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
78441 		DUK_ASSERT(h != NULL);
78442 		return (DUK_HSTRING_GET_BYTELEN(h) > 0 ? 1 : 0);
78443 	}
78444 	case DUK_TAG_OBJECT: {
78445 		return 1;
78446 	}
78447 	case DUK_TAG_BUFFER: {
78448 		/* Mimic Uint8Array semantics: objects coerce true, regardless
78449 		 * of buffer length (zero or not) or context.
78450 		 */
78451 		return 1;
78452 	}
78453 	case DUK_TAG_POINTER: {
78454 		void *p = DUK_TVAL_GET_POINTER(tv);
78455 		return (p != NULL ? 1 : 0);
78456 	}
78457 	case DUK_TAG_LIGHTFUNC: {
78458 		return 1;
78459 	}
78460 #if defined(DUK_USE_FASTINT)
78461 	case DUK_TAG_FASTINT:
78462 		if (DUK_TVAL_GET_FASTINT(tv) != 0) {
78463 			return 1;
78464 		} else {
78465 			return 0;
78466 		}
78467 #endif
78468 	default: {
78469 		/* number */
78470 		duk_double_t d;
78471 #if defined(DUK_USE_PREFER_SIZE)
78472 		int c;
78473 #endif
78474 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
78475 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
78476 		d = DUK_TVAL_GET_DOUBLE(tv);
78477 #if defined(DUK_USE_PREFER_SIZE)
78478 		c = DUK_FPCLASSIFY((double) d);
78479 		if (c == DUK_FP_ZERO || c == DUK_FP_NAN) {
78480 			return 0;
78481 		} else {
78482 			return 1;
78483 		}
78484 #else
78485 		DUK_ASSERT(duk_double_is_nan_or_zero(d) == 0 || duk_double_is_nan_or_zero(d) == 1);
78486 		return duk_double_is_nan_or_zero(d) ^ 1;
78487 #endif
78488 	}
78489 	}
78490 	DUK_UNREACHABLE();
78491 }
78492 
78493 /*
78494  *  ToNumber()  (E5 Section 9.3)
78495  *
78496  *  Value to convert must be on stack top, and is popped before exit.
78497  *
78498  *  See: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
78499  *       http://www.cs.indiana.edu/~burger/fp/index.html
78500  *
78501  *  Notes on the conversion:
78502  *
78503  *    - There are specific requirements on the accuracy of the conversion
78504  *      through a "Mathematical Value" (MV), so this conversion is not
78505  *      trivial.
78506  *
78507  *    - Quick rejects (e.g. based on first char) are difficult because
78508  *      the grammar allows leading and trailing white space.
78509  *
78510  *    - Quick reject based on string length is difficult even after
78511  *      accounting for white space; there may be arbitrarily many
78512  *      decimal digits.
78513  *
78514  *    - Standard grammar allows decimal values ("123"), hex values
78515  *      ("0x123") and infinities
78516  *
78517  *    - Unlike source code literals, ToNumber() coerces empty strings
78518  *      and strings with only whitespace to zero (not NaN).
78519  */
78520 
78521 /* E5 Section 9.3.1 */
78522 DUK_LOCAL duk_double_t duk__tonumber_string_raw(duk_hthread *thr) {
78523 	duk_small_uint_t s2n_flags;
78524 	duk_double_t d;
78525 
78526 	DUK_ASSERT(duk_is_string(thr, -1));
78527 
78528 	/* Quite lenient, e.g. allow empty as zero, but don't allow trailing
78529 	 * garbage.
78530 	 */
78531 	s2n_flags = DUK_S2N_FLAG_TRIM_WHITE |
78532 	            DUK_S2N_FLAG_ALLOW_EXP |
78533 	            DUK_S2N_FLAG_ALLOW_PLUS |
78534 	            DUK_S2N_FLAG_ALLOW_MINUS |
78535 	            DUK_S2N_FLAG_ALLOW_INF |
78536 	            DUK_S2N_FLAG_ALLOW_FRAC |
78537 	            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
78538 	            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
78539 	            DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO |
78540 	            DUK_S2N_FLAG_ALLOW_LEADING_ZERO |
78541 	            DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT |
78542 	            DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT |
78543 	            DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT;
78544 
78545 	duk_numconv_parse(thr, 10 /*radix*/, s2n_flags);
78546 
78547 #if defined(DUK_USE_PREFER_SIZE)
78548 	d = duk_get_number(thr, -1);
78549 	duk_pop_unsafe(thr);
78550 #else
78551 	thr->valstack_top--;
78552 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(thr->valstack_top));
78553 	DUK_ASSERT(DUK_TVAL_IS_DOUBLE(thr->valstack_top));  /* no fastint conversion in numconv now */
78554 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(thr->valstack_top));
78555 	d = DUK_TVAL_GET_DOUBLE(thr->valstack_top);  /* assumes not a fastint */
78556 	DUK_TVAL_SET_UNDEFINED(thr->valstack_top);
78557 #endif
78558 
78559 	return d;
78560 }
78561 
78562 DUK_INTERNAL duk_double_t duk_js_tonumber(duk_hthread *thr, duk_tval *tv) {
78563 	DUK_ASSERT(thr != NULL);
78564 	DUK_ASSERT(tv != NULL);
78565 
78566 	switch (DUK_TVAL_GET_TAG(tv)) {
78567 	case DUK_TAG_UNDEFINED: {
78568 		/* return a specific NaN (although not strictly necessary) */
78569 		duk_double_union du;
78570 		DUK_DBLUNION_SET_NAN(&du);
78571 		DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
78572 		return du.d;
78573 	}
78574 	case DUK_TAG_NULL: {
78575 		/* +0.0 */
78576 		return 0.0;
78577 	}
78578 	case DUK_TAG_BOOLEAN: {
78579 		if (DUK_TVAL_IS_BOOLEAN_TRUE(tv)) {
78580 			return 1.0;
78581 		}
78582 		return 0.0;
78583 	}
78584 	case DUK_TAG_STRING: {
78585 		/* For Symbols ToNumber() is always a TypeError. */
78586 		duk_hstring *h = DUK_TVAL_GET_STRING(tv);
78587 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(h))) {
78588 			DUK_ERROR_TYPE(thr, DUK_STR_CANNOT_NUMBER_COERCE_SYMBOL);
78589 			DUK_WO_NORETURN(return 0.0;);
78590 		}
78591 		duk_push_hstring(thr, h);
78592 		return duk__tonumber_string_raw(thr);
78593 	}
78594 	case DUK_TAG_BUFFER:  /* plain buffer treated like object */
78595 	case DUK_TAG_OBJECT: {
78596 		duk_double_t d;
78597 		duk_push_tval(thr, tv);
78598 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);  /* 'tv' becomes invalid */
78599 
78600 		/* recursive call for a primitive value (guaranteed not to cause second
78601 		 * recursion).
78602 		 */
78603 		DUK_ASSERT(duk_get_tval(thr, -1) != NULL);
78604 		d = duk_js_tonumber(thr, duk_get_tval(thr, -1));
78605 
78606 		duk_pop_unsafe(thr);
78607 		return d;
78608 	}
78609 	case DUK_TAG_POINTER: {
78610 		/* Coerce like boolean */
78611 		void *p = DUK_TVAL_GET_POINTER(tv);
78612 		return (p != NULL ? 1.0 : 0.0);
78613 	}
78614 	case DUK_TAG_LIGHTFUNC: {
78615 		/* +(function(){}) -> NaN */
78616 		return DUK_DOUBLE_NAN;
78617 	}
78618 #if defined(DUK_USE_FASTINT)
78619 	case DUK_TAG_FASTINT:
78620 		return (duk_double_t) DUK_TVAL_GET_FASTINT(tv);
78621 #endif
78622 	default: {
78623 		/* number */
78624 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv));
78625 		DUK_ASSERT(DUK_TVAL_IS_DOUBLE(tv));
78626 		return DUK_TVAL_GET_DOUBLE(tv);
78627 	}
78628 	}
78629 
78630 	DUK_UNREACHABLE();
78631 }
78632 
78633 /*
78634  *  ToInteger()  (E5 Section 9.4)
78635  */
78636 
78637 /* exposed, used by e.g. duk_bi_date.c */
78638 DUK_INTERNAL duk_double_t duk_js_tointeger_number(duk_double_t x) {
78639 #if defined(DUK_USE_PREFER_SIZE)
78640 	duk_small_int_t c = (duk_small_int_t) DUK_FPCLASSIFY(x);
78641 
78642 	if (DUK_UNLIKELY(c == DUK_FP_NAN)) {
78643 		return 0.0;
78644 	} else if (DUK_UNLIKELY(c == DUK_FP_INFINITE)) {
78645 		return x;
78646 	} else {
78647 		/* Finite, including neg/pos zero.  Neg zero sign must be
78648 		 * preserved.
78649 		 */
78650 		return duk_double_trunc_towards_zero(x);
78651 	}
78652 #else  /* DUK_USE_PREFER_SIZE */
78653 	/* NaN and Infinity have the same exponent so it's a cheap
78654 	 * initial check for the rare path.
78655 	 */
78656 	if (DUK_UNLIKELY(duk_double_is_nan_or_inf(x) != 0U)) {
78657 		if (duk_double_is_nan(x)) {
78658 			return 0.0;
78659 		} else {
78660 			return x;
78661 		}
78662 	} else {
78663 		return duk_double_trunc_towards_zero(x);
78664 	}
78665 #endif  /* DUK_USE_PREFER_SIZE */
78666 }
78667 
78668 DUK_INTERNAL duk_double_t duk_js_tointeger(duk_hthread *thr, duk_tval *tv) {
78669 	/* XXX: fastint */
78670 	duk_double_t d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78671 	return duk_js_tointeger_number(d);
78672 }
78673 
78674 /*
78675  *  ToInt32(), ToUint32(), ToUint16()  (E5 Sections 9.5, 9.6, 9.7)
78676  */
78677 
78678 /* combined algorithm matching E5 Sections 9.5 and 9.6 */
78679 DUK_LOCAL duk_double_t duk__toint32_touint32_helper(duk_double_t x, duk_bool_t is_toint32) {
78680 #if defined (DUK_USE_PREFER_SIZE)
78681 	duk_small_int_t c;
78682 #endif
78683 
78684 #if defined (DUK_USE_PREFER_SIZE)
78685 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
78686 	if (c == DUK_FP_NAN || c == DUK_FP_ZERO || c == DUK_FP_INFINITE) {
78687 		return 0.0;
78688 	}
78689 #else
78690 	if (duk_double_is_nan_zero_inf(x)) {
78691 		return 0.0;
78692 	}
78693 #endif
78694 
78695 	/* x = sign(x) * floor(abs(x)), i.e. truncate towards zero, keep sign */
78696 	x = duk_double_trunc_towards_zero(x);
78697 
78698 	/* NOTE: fmod(x) result sign is same as sign of x, which
78699 	 * differs from what Javascript wants (see Section 9.6).
78700 	 */
78701 
78702 	x = DUK_FMOD(x, DUK_DOUBLE_2TO32);    /* -> x in ]-2**32, 2**32[ */
78703 
78704 	if (x < 0.0) {
78705 		x += DUK_DOUBLE_2TO32;
78706 	}
78707 	DUK_ASSERT(x >= 0 && x < DUK_DOUBLE_2TO32);  /* -> x in [0, 2**32[ */
78708 
78709 	if (is_toint32) {
78710 		if (x >= DUK_DOUBLE_2TO31) {
78711 			/* x in [2**31, 2**32[ */
78712 
78713 			x -= DUK_DOUBLE_2TO32;  /* -> x in [-2**31,2**31[ */
78714 		}
78715 	}
78716 
78717 	return x;
78718 }
78719 
78720 DUK_INTERNAL duk_int32_t duk_js_toint32(duk_hthread *thr, duk_tval *tv) {
78721 	duk_double_t d;
78722 
78723 #if defined(DUK_USE_FASTINT)
78724 	if (DUK_TVAL_IS_FASTINT(tv)) {
78725 		return DUK_TVAL_GET_FASTINT_I32(tv);
78726 	}
78727 #endif
78728 
78729 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78730 	d = duk__toint32_touint32_helper(d, 1);
78731 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
78732 	DUK_ASSERT(d >= -2147483648.0 && d <= 2147483647.0);  /* [-0x80000000,0x7fffffff] */
78733 	DUK_ASSERT(d == ((duk_double_t) ((duk_int32_t) d)));  /* whole, won't clip */
78734 	return (duk_int32_t) d;
78735 }
78736 
78737 
78738 DUK_INTERNAL duk_uint32_t duk_js_touint32(duk_hthread *thr, duk_tval *tv) {
78739 	duk_double_t d;
78740 
78741 #if defined(DUK_USE_FASTINT)
78742 	if (DUK_TVAL_IS_FASTINT(tv)) {
78743 		return DUK_TVAL_GET_FASTINT_U32(tv);
78744 	}
78745 #endif
78746 
78747 	d = duk_js_tonumber(thr, tv);  /* invalidates tv */
78748 	d = duk__toint32_touint32_helper(d, 0);
78749 	DUK_ASSERT(DUK_FPCLASSIFY(d) == DUK_FP_ZERO || DUK_FPCLASSIFY(d) == DUK_FP_NORMAL);
78750 	DUK_ASSERT(d >= 0.0 && d <= 4294967295.0);  /* [0x00000000, 0xffffffff] */
78751 	DUK_ASSERT(d == ((duk_double_t) ((duk_uint32_t) d)));  /* whole, won't clip */
78752 	return (duk_uint32_t) d;
78753 
78754 }
78755 
78756 DUK_INTERNAL duk_uint16_t duk_js_touint16(duk_hthread *thr, duk_tval *tv) {
78757 	/* should be a safe way to compute this */
78758 	return (duk_uint16_t) (duk_js_touint32(thr, tv) & 0x0000ffffU);
78759 }
78760 
78761 /*
78762  *  ToString()  (E5 Section 9.8)
78763  *  ToObject()  (E5 Section 9.9)
78764  *  CheckObjectCoercible()  (E5 Section 9.10)
78765  *  IsCallable()  (E5 Section 9.11)
78766  *
78767  *  ==> implemented in the API.
78768  */
78769 
78770 /*
78771  *  Loose equality, strict equality, and SameValue (E5 Sections 11.9.1, 11.9.4,
78772  *  9.12).  These have much in common so they can share some helpers.
78773  *
78774  *  Future work notes:
78775  *
78776  *    - Current implementation (and spec definition) has recursion; this should
78777  *      be fixed if possible.
78778  *
78779  *    - String-to-number coercion should be possible without going through the
78780  *      value stack (and be more compact) if a shared helper is invoked.
78781  */
78782 
78783 /* Note that this is the same operation for strict and loose equality:
78784  *  - E5 Section 11.9.3, step 1.c (loose)
78785  *  - E5 Section 11.9.6, step 4 (strict)
78786  */
78787 
78788 DUK_LOCAL duk_bool_t duk__js_equals_number(duk_double_t x, duk_double_t y) {
78789 #if defined(DUK_USE_PARANOID_MATH)
78790 	/* Straightforward algorithm, makes fewer compiler assumptions. */
78791 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78792 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78793 	if (cx == DUK_FP_NAN || cy == DUK_FP_NAN) {
78794 		return 0;
78795 	}
78796 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
78797 		return 1;
78798 	}
78799 	if (x == y) {
78800 		return 1;
78801 	}
78802 	return 0;
78803 #else  /* DUK_USE_PARANOID_MATH */
78804 	/* Better equivalent algorithm.  If the compiler is compliant, C and
78805 	 * ECMAScript semantics are identical for this particular comparison.
78806 	 * In particular, NaNs must never compare equal and zeroes must compare
78807 	 * equal regardless of sign.  Could also use a macro, but this inlines
78808 	 * already nicely (no difference on gcc, for instance).
78809 	 */
78810 	if (x == y) {
78811 		/* IEEE requires that NaNs compare false */
78812 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
78813 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
78814 		return 1;
78815 	} else {
78816 		/* IEEE requires that zeros compare the same regardless
78817 		 * of their signed, so if both x and y are zeroes, they
78818 		 * are caught above.
78819 		 */
78820 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
78821 		return 0;
78822 	}
78823 #endif  /* DUK_USE_PARANOID_MATH */
78824 }
78825 
78826 DUK_LOCAL duk_bool_t duk__js_samevalue_number(duk_double_t x, duk_double_t y) {
78827 #if defined(DUK_USE_PARANOID_MATH)
78828 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78829 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78830 
78831 	if (cx == DUK_FP_NAN && cy == DUK_FP_NAN) {
78832 		/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
78833 		return 1;
78834 	}
78835 	if (cx == DUK_FP_ZERO && cy == DUK_FP_ZERO) {
78836 		/* Note: cannot assume that a non-zero return value of signbit() would
78837 		 * always be the same -- hence cannot (portably) use something like:
78838 		 *
78839 		 *     signbit(x) == signbit(y)
78840 		 */
78841 		duk_small_int_t sx = DUK_SIGNBIT(x) ? 1 : 0;
78842 		duk_small_int_t sy = DUK_SIGNBIT(y) ? 1 : 0;
78843 		return (sx == sy);
78844 	}
78845 
78846 	/* normal comparison; known:
78847 	 *   - both x and y are not NaNs (but one of them can be)
78848 	 *   - both x and y are not zero (but one of them can be)
78849 	 *   - x and y may be denormal or infinite
78850 	 */
78851 
78852 	return (x == y);
78853 #else  /* DUK_USE_PARANOID_MATH */
78854 	duk_small_int_t cx = (duk_small_int_t) DUK_FPCLASSIFY(x);
78855 	duk_small_int_t cy = (duk_small_int_t) DUK_FPCLASSIFY(y);
78856 
78857 	if (x == y) {
78858 		/* IEEE requires that NaNs compare false */
78859 		DUK_ASSERT(DUK_FPCLASSIFY(x) != DUK_FP_NAN);
78860 		DUK_ASSERT(DUK_FPCLASSIFY(y) != DUK_FP_NAN);
78861 
78862 		/* Using classification has smaller footprint than direct comparison. */
78863 		if (DUK_UNLIKELY(cx == DUK_FP_ZERO && cy == DUK_FP_ZERO)) {
78864 			/* Note: cannot assume that a non-zero return value of signbit() would
78865 			 * always be the same -- hence cannot (portably) use something like:
78866 			 *
78867 			 *     signbit(x) == signbit(y)
78868 			 */
78869 			return duk_double_same_sign(x, y);
78870 		}
78871 		return 1;
78872 	} else {
78873 		/* IEEE requires that zeros compare the same regardless
78874 		 * of their sign, so if both x and y are zeroes, they
78875 		 * are caught above.
78876 		 */
78877 		DUK_ASSERT(!(DUK_FPCLASSIFY(x) == DUK_FP_ZERO && DUK_FPCLASSIFY(y) == DUK_FP_ZERO));
78878 
78879 		/* Difference to non-strict/strict comparison is that NaNs compare
78880 		 * equal and signed zero signs matter.
78881 		 */
78882 		if (DUK_UNLIKELY(cx == DUK_FP_NAN && cy == DUK_FP_NAN)) {
78883 			/* SameValue(NaN, NaN) = true, regardless of NaN sign or extra bits */
78884 			return 1;
78885 		}
78886 		return 0;
78887 	}
78888 #endif  /* DUK_USE_PARANOID_MATH */
78889 }
78890 
78891 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) {
78892 	duk_uint_t type_mask_x;
78893 	duk_uint_t type_mask_y;
78894 
78895 	/* If flags != 0 (strict or SameValue), thr can be NULL.  For loose
78896 	 * equals comparison it must be != NULL.
78897 	 */
78898 	DUK_ASSERT(flags != 0 || thr != NULL);
78899 
78900 	/*
78901 	 *  Same type?
78902 	 *
78903 	 *  Note: since number values have no explicit tag in the 8-byte
78904 	 *  representation, need the awkward if + switch.
78905 	 */
78906 
78907 #if defined(DUK_USE_FASTINT)
78908 	if (DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y)) {
78909 		if (DUK_TVAL_GET_FASTINT(tv_x) == DUK_TVAL_GET_FASTINT(tv_y)) {
78910 			return 1;
78911 		} else {
78912 			return 0;
78913 		}
78914 	}
78915 	else
78916 #endif
78917 	if (DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y)) {
78918 		duk_double_t d1, d2;
78919 
78920 		/* Catches both doubles and cases where only one argument is
78921 		 * a fastint so can't assume a double.
78922 		 */
78923 		d1 = DUK_TVAL_GET_NUMBER(tv_x);
78924 		d2 = DUK_TVAL_GET_NUMBER(tv_y);
78925 		if (DUK_UNLIKELY((flags & DUK_EQUALS_FLAG_SAMEVALUE) != 0)) {
78926 			/* SameValue */
78927 			return duk__js_samevalue_number(d1, d2);
78928 		} else {
78929 			/* equals and strict equals */
78930 			return duk__js_equals_number(d1, d2);
78931 		}
78932 	} else if (DUK_TVAL_GET_TAG(tv_x) == DUK_TVAL_GET_TAG(tv_y)) {
78933 		switch (DUK_TVAL_GET_TAG(tv_x)) {
78934 		case DUK_TAG_UNDEFINED:
78935 		case DUK_TAG_NULL: {
78936 			return 1;
78937 		}
78938 		case DUK_TAG_BOOLEAN: {
78939 			return DUK_TVAL_GET_BOOLEAN(tv_x) == DUK_TVAL_GET_BOOLEAN(tv_y);
78940 		}
78941 		case DUK_TAG_POINTER: {
78942 			return DUK_TVAL_GET_POINTER(tv_x) == DUK_TVAL_GET_POINTER(tv_y);
78943 		}
78944 		case DUK_TAG_STRING:
78945 		case DUK_TAG_OBJECT: {
78946 			/* Heap pointer comparison suffices for strings and objects.
78947 			 * Symbols compare equal if they have the same internal
78948 			 * representation; again heap pointer comparison suffices.
78949 			 */
78950 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
78951 		}
78952 		case DUK_TAG_BUFFER: {
78953 			/* In Duktape 2.x plain buffers mimic Uint8Array objects
78954 			 * so always compare by heap pointer.  In Duktape 1.x
78955 			 * strict comparison would compare heap pointers and
78956 			 * non-strict would compare contents.
78957 			 */
78958 			return DUK_TVAL_GET_HEAPHDR(tv_x) == DUK_TVAL_GET_HEAPHDR(tv_y);
78959 		}
78960 		case DUK_TAG_LIGHTFUNC: {
78961 			/* At least 'magic' has a significant impact on function
78962 			 * identity.
78963 			 */
78964 			duk_small_uint_t lf_flags_x;
78965 			duk_small_uint_t lf_flags_y;
78966 			duk_c_function func_x;
78967 			duk_c_function func_y;
78968 
78969 			DUK_TVAL_GET_LIGHTFUNC(tv_x, func_x, lf_flags_x);
78970 			DUK_TVAL_GET_LIGHTFUNC(tv_y, func_y, lf_flags_y);
78971 			return ((func_x == func_y) && (lf_flags_x == lf_flags_y)) ? 1 : 0;
78972 		}
78973 #if defined(DUK_USE_FASTINT)
78974 		case DUK_TAG_FASTINT:
78975 #endif
78976 		default: {
78977 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
78978 			DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_y));
78979 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
78980 			DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_y));
78981 			DUK_UNREACHABLE();
78982 			return 0;
78983 		}
78984 		}
78985 	}
78986 
78987 	if ((flags & (DUK_EQUALS_FLAG_STRICT | DUK_EQUALS_FLAG_SAMEVALUE)) != 0) {
78988 		return 0;
78989 	}
78990 
78991 	DUK_ASSERT(flags == 0);  /* non-strict equality from here on */
78992 
78993 	/*
78994 	 *  Types are different; various cases for non-strict comparison
78995 	 *
78996 	 *  Since comparison is symmetric, we use a "swap trick" to reduce
78997 	 *  code size.
78998 	 */
78999 
79000 	type_mask_x = duk_get_type_mask_tval(tv_x);
79001 	type_mask_y = duk_get_type_mask_tval(tv_y);
79002 
79003 	/* Undefined/null are considered equal (e.g. "null == undefined" -> true). */
79004 	if ((type_mask_x & (DUK_TYPE_MASK_UNDEFINED | DUK_TYPE_MASK_NULL)) &&
79005 	    (type_mask_y & (DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_UNDEFINED))) {
79006 		return 1;
79007 	}
79008 
79009 	/* Number/string -> coerce string to number (e.g. "'1.5' == 1.5" -> true). */
79010 	if ((type_mask_x & DUK_TYPE_MASK_NUMBER) && (type_mask_y & DUK_TYPE_MASK_STRING)) {
79011 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_y)) {
79012 			duk_double_t d1, d2;
79013 			d1 = DUK_TVAL_GET_NUMBER(tv_x);
79014 			d2 = duk_to_number_tval(thr, tv_y);
79015 			return duk__js_equals_number(d1, d2);
79016 		}
79017 	}
79018 	if ((type_mask_x & DUK_TYPE_MASK_STRING) && (type_mask_y & DUK_TYPE_MASK_NUMBER)) {
79019 		if (!DUK_TVAL_STRING_IS_SYMBOL(tv_x)) {
79020 			duk_double_t d1, d2;
79021 			d1 = DUK_TVAL_GET_NUMBER(tv_y);
79022 			d2 = duk_to_number_tval(thr, tv_x);
79023 			return duk__js_equals_number(d1, d2);
79024 		}
79025 	}
79026 
79027 	/* Boolean/any -> coerce boolean to number and try again.  If boolean is
79028 	 * compared to a pointer, the final comparison after coercion now always
79029 	 * yields false (as pointer vs. number compares to false), but this is
79030 	 * not special cased.
79031 	 *
79032 	 * ToNumber(bool) is +1.0 or 0.0.  Tagged boolean value is always 0 or 1.
79033 	 */
79034 	if (type_mask_x & DUK_TYPE_MASK_BOOLEAN) {
79035 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_x) == 0 || DUK_TVAL_GET_BOOLEAN(tv_x) == 1);
79036 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_x));
79037 		duk_push_tval(thr, tv_y);
79038 		goto recursive_call;
79039 	}
79040 	if (type_mask_y & DUK_TYPE_MASK_BOOLEAN) {
79041 		DUK_ASSERT(DUK_TVAL_GET_BOOLEAN(tv_y) == 0 || DUK_TVAL_GET_BOOLEAN(tv_y) == 1);
79042 		duk_push_tval(thr, tv_x);
79043 		duk_push_uint(thr, DUK_TVAL_GET_BOOLEAN(tv_y));
79044 		goto recursive_call;
79045 	}
79046 
79047 	/* String-number-symbol/object -> coerce object to primitive (apparently without hint), then try again. */
79048 	if ((type_mask_x & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER)) &&
79049 	    (type_mask_y & DUK_TYPE_MASK_OBJECT)) {
79050 		/* No symbol check needed because symbols and strings are accepted. */
79051 		duk_push_tval(thr, tv_x);
79052 		duk_push_tval(thr, tv_y);
79053 		duk_to_primitive(thr, -1, DUK_HINT_NONE);  /* apparently no hint? */
79054 		goto recursive_call;
79055 	}
79056 	if ((type_mask_x & DUK_TYPE_MASK_OBJECT) &&
79057 	    (type_mask_y & (DUK_TYPE_MASK_STRING | DUK_TYPE_MASK_NUMBER))) {
79058 		/* No symbol check needed because symbols and strings are accepted. */
79059 		duk_push_tval(thr, tv_x);
79060 		duk_push_tval(thr, tv_y);
79061 		duk_to_primitive(thr, -2, DUK_HINT_NONE);  /* apparently no hint? */
79062 		goto recursive_call;
79063 	}
79064 
79065 	/* Nothing worked -> not equal. */
79066 	return 0;
79067 
79068  recursive_call:
79069 	/* Shared code path to call the helper again with arguments on stack top. */
79070 	{
79071 		duk_bool_t rc;
79072 		rc = duk_js_equals_helper(thr,
79073 		                          DUK_GET_TVAL_NEGIDX(thr, -2),
79074 		                          DUK_GET_TVAL_NEGIDX(thr, -1),
79075 		                          0 /*flags:nonstrict*/);
79076 		duk_pop_2_unsafe(thr);
79077 		return rc;
79078 	}
79079 }
79080 
79081 /*
79082  *  Comparisons (x >= y, x > y, x <= y, x < y)
79083  *
79084  *  E5 Section 11.8.5: implement 'x < y' and then use negate and eval_left_first
79085  *  flags to get the rest.
79086  */
79087 
79088 /* XXX: this should probably just operate on the stack top, because it
79089  * needs to push stuff on the stack anyway...
79090  */
79091 
79092 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) {
79093 	duk_size_t prefix_len;
79094 	duk_small_int_t rc;
79095 
79096 	prefix_len = (len1 <= len2 ? len1 : len2);
79097 
79098 	/* duk_memcmp() is guaranteed to return zero (equal) for zero length
79099 	 * inputs.
79100 	 */
79101 	rc = duk_memcmp_unsafe((const void *) buf1,
79102 	                       (const void *) buf2,
79103 	                       (size_t) prefix_len);
79104 
79105 	if (rc < 0) {
79106 		return -1;
79107 	} else if (rc > 0) {
79108 		return 1;
79109 	}
79110 
79111 	/* prefix matches, lengths matter now */
79112 	if (len1 < len2) {
79113 		/* e.g. "x" < "xx" */
79114 		return -1;
79115 	} else if (len1 > len2) {
79116 		return 1;
79117 	}
79118 
79119 	return 0;
79120 }
79121 
79122 DUK_INTERNAL duk_small_int_t duk_js_string_compare(duk_hstring *h1, duk_hstring *h2) {
79123 	/*
79124 	 *  String comparison (E5 Section 11.8.5, step 4), which
79125 	 *  needs to compare codepoint by codepoint.
79126 	 *
79127 	 *  However, UTF-8 allows us to use strcmp directly: the shared
79128 	 *  prefix will be encoded identically (UTF-8 has unique encoding)
79129 	 *  and the first differing character can be compared with a simple
79130 	 *  unsigned byte comparison (which strcmp does).
79131 	 *
79132 	 *  This will not work properly for non-xutf-8 strings, but this
79133 	 *  is not an issue for compliance.
79134 	 */
79135 
79136 	DUK_ASSERT(h1 != NULL);
79137 	DUK_ASSERT(h2 != NULL);
79138 
79139 	return duk_js_data_compare((const duk_uint8_t *) DUK_HSTRING_GET_DATA(h1),
79140 	                           (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h2),
79141 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h1),
79142 	                           (duk_size_t) DUK_HSTRING_GET_BYTELEN(h2));
79143 }
79144 
79145 #if 0  /* unused */
79146 DUK_INTERNAL duk_small_int_t duk_js_buffer_compare(duk_heap *heap, duk_hbuffer *h1, duk_hbuffer *h2) {
79147 	/* Similar to String comparison. */
79148 
79149 	DUK_ASSERT(h1 != NULL);
79150 	DUK_ASSERT(h2 != NULL);
79151 	DUK_UNREF(heap);
79152 
79153 	return duk_js_data_compare((const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h1),
79154 	                           (const duk_uint8_t *) DUK_HBUFFER_GET_DATA_PTR(heap, h2),
79155 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h1),
79156 	                           (duk_size_t) DUK_HBUFFER_GET_SIZE(h2));
79157 }
79158 #endif
79159 
79160 #if defined(DUK_USE_FASTINT)
79161 DUK_LOCAL duk_bool_t duk__compare_fastint(duk_bool_t retval, duk_int64_t v1, duk_int64_t v2) {
79162 	DUK_ASSERT(retval == 0 || retval == 1);
79163 	if (v1 < v2) {
79164 		return retval ^ 1;
79165 	} else {
79166 		return retval;
79167 	}
79168 }
79169 #endif
79170 
79171 #if defined(DUK_USE_PARANOID_MATH)
79172 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79173 	duk_small_int_t c1, s1, c2, s2;
79174 
79175 	DUK_ASSERT(retval == 0 || retval == 1);
79176 	c1 = (duk_small_int_t) DUK_FPCLASSIFY(d1);
79177 	s1 = (duk_small_int_t) DUK_SIGNBIT(d1);
79178 	c2 = (duk_small_int_t) DUK_FPCLASSIFY(d2);
79179 	s2 = (duk_small_int_t) DUK_SIGNBIT(d2);
79180 
79181 	if (c1 == DUK_FP_NAN || c2 == DUK_FP_NAN) {
79182 		return 0;  /* Always false, regardless of negation. */
79183 	}
79184 
79185 	if (c1 == DUK_FP_ZERO && c2 == DUK_FP_ZERO) {
79186 		/* For all combinations: +0 < +0, +0 < -0, -0 < +0, -0 < -0,
79187 		 * steps e, f, and g.
79188 		 */
79189 		return retval;  /* false */
79190 	}
79191 
79192 	if (d1 == d2) {
79193 		return retval;  /* false */
79194 	}
79195 
79196 	if (c1 == DUK_FP_INFINITE && s1 == 0) {
79197 		/* x == +Infinity */
79198 		return retval;  /* false */
79199 	}
79200 
79201 	if (c2 == DUK_FP_INFINITE && s2 == 0) {
79202 		/* y == +Infinity */
79203 		return retval ^ 1;  /* true */
79204 	}
79205 
79206 	if (c2 == DUK_FP_INFINITE && s2 != 0) {
79207 		/* y == -Infinity */
79208 		return retval;  /* false */
79209 	}
79210 
79211 	if (c1 == DUK_FP_INFINITE && s1 != 0) {
79212 		/* x == -Infinity */
79213 		return retval ^ 1;  /* true */
79214 	}
79215 
79216 	if (d1 < d2) {
79217 		return retval ^ 1;  /* true */
79218 	}
79219 
79220 	return retval;  /* false */
79221 }
79222 #else  /* DUK_USE_PARANOID_MATH */
79223 DUK_LOCAL duk_bool_t duk__compare_number(duk_bool_t retval, duk_double_t d1, duk_double_t d2) {
79224 	/* This comparison tree relies doesn't match the exact steps in
79225 	 * E5 Section 11.8.5 but should produce the same results.  The
79226 	 * steps rely on exact IEEE semantics for NaNs, etc.
79227 	 */
79228 
79229 	DUK_ASSERT(retval == 0 || retval == 1);
79230 	if (d1 < d2) {
79231 		/* In no case should both (d1 < d2) and (d2 < d1) be true.
79232 		 * It's possible that neither is true though, and that's
79233 		 * handled below.
79234 		 */
79235 		DUK_ASSERT(!(d2 < d1));
79236 
79237 		/* - d1 < d2, both d1/d2 are normals (not Infinity, not NaN)
79238 		 * - d2 is +Infinity, d1 != +Infinity and NaN
79239 		 * - d1 is -Infinity, d2 != -Infinity and NaN
79240 		 */
79241 		return retval ^ 1;
79242 	} else {
79243 		if (d2 < d1) {
79244 			/* - !(d1 < d2), both d1/d2 are normals (not Infinity, not NaN)
79245 			 * - d1 is +Infinity, d2 != +Infinity and NaN
79246 			 * - d2 is -Infinity, d1 != -Infinity and NaN
79247 			 */
79248 			return retval;
79249 		} else {
79250 			/* - d1 and/or d2 is NaN
79251 			 * - d1 and d2 are both +/- 0
79252 			 * - d1 == d2 (including infinities)
79253 			 */
79254 			if (duk_double_is_nan(d1) || duk_double_is_nan(d2)) {
79255 				/* Note: undefined from Section 11.8.5 always
79256 				 * results in false return (see e.g. Section
79257 				 * 11.8.3) - hence special treatment here.
79258 				 */
79259 				return 0;  /* zero regardless of negation */
79260 			} else {
79261 				return retval;
79262 			}
79263 		}
79264 	}
79265 }
79266 #endif  /* DUK_USE_PARANOID_MATH */
79267 
79268 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) {
79269 	duk_double_t d1, d2;
79270 	duk_small_int_t rc;
79271 	duk_bool_t retval;
79272 
79273 	DUK_ASSERT(DUK_COMPARE_FLAG_NEGATE == 1);  /* Rely on this flag being lowest. */
79274 	retval = flags & DUK_COMPARE_FLAG_NEGATE;
79275 	DUK_ASSERT(retval == 0 || retval == 1);
79276 
79277 	/* Fast path for fastints */
79278 #if defined(DUK_USE_FASTINT)
79279 	if (DUK_LIKELY(DUK_TVAL_IS_FASTINT(tv_x) && DUK_TVAL_IS_FASTINT(tv_y))) {
79280 		return duk__compare_fastint(retval,
79281 		                            DUK_TVAL_GET_FASTINT(tv_x),
79282 		                            DUK_TVAL_GET_FASTINT(tv_y));
79283 	}
79284 #endif  /* DUK_USE_FASTINT */
79285 
79286 	/* Fast path for numbers (one of which may be a fastint) */
79287 #if !defined(DUK_USE_PREFER_SIZE)
79288 	if (DUK_LIKELY(DUK_TVAL_IS_NUMBER(tv_x) && DUK_TVAL_IS_NUMBER(tv_y))) {
79289 		return duk__compare_number(retval,
79290 		                           DUK_TVAL_GET_NUMBER(tv_x),
79291 		                           DUK_TVAL_GET_NUMBER(tv_y));
79292 	}
79293 #endif
79294 
79295 	/* Slow path */
79296 
79297 	duk_push_tval(thr, tv_x);
79298 	duk_push_tval(thr, tv_y);
79299 
79300 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
79301 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79302 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79303 	} else {
79304 		duk_to_primitive(thr, -1, DUK_HINT_NUMBER);
79305 		duk_to_primitive(thr, -2, DUK_HINT_NUMBER);
79306 	}
79307 
79308 	/* Note: reuse variables */
79309 	tv_x = DUK_GET_TVAL_NEGIDX(thr, -2);
79310 	tv_y = DUK_GET_TVAL_NEGIDX(thr, -1);
79311 
79312 	if (DUK_TVAL_IS_STRING(tv_x) && DUK_TVAL_IS_STRING(tv_y)) {
79313 		duk_hstring *h1 = DUK_TVAL_GET_STRING(tv_x);
79314 		duk_hstring *h2 = DUK_TVAL_GET_STRING(tv_y);
79315 		DUK_ASSERT(h1 != NULL);
79316 		DUK_ASSERT(h2 != NULL);
79317 
79318 		if (DUK_LIKELY(!DUK_HSTRING_HAS_SYMBOL(h1) && !DUK_HSTRING_HAS_SYMBOL(h2))) {
79319 			rc = duk_js_string_compare(h1, h2);
79320 			duk_pop_2_unsafe(thr);
79321 			if (rc < 0) {
79322 				return retval ^ 1;
79323 			} else {
79324 				return retval;
79325 			}
79326 		}
79327 
79328 		/* One or both are Symbols: fall through to handle in the
79329 		 * generic path.  Concretely, ToNumber() will fail.
79330 		 */
79331 	}
79332 
79333 	/* Ordering should not matter (E5 Section 11.8.5, step 3.a). */
79334 #if 0
79335 	if (flags & DUK_COMPARE_FLAG_EVAL_LEFT_FIRST) {
79336 		d1 = duk_to_number_m2(thr);
79337 		d2 = duk_to_number_m1(thr);
79338 	} else {
79339 		d2 = duk_to_number_m1(thr);
79340 		d1 = duk_to_number_m2(thr);
79341 	}
79342 #endif
79343 	d1 = duk_to_number_m2(thr);
79344 	d2 = duk_to_number_m1(thr);
79345 
79346 	/* We want to duk_pop_2_unsafe(thr); because the values are numbers
79347 	 * no decref check is needed.
79348 	 */
79349 #if defined(DUK_USE_PREFER_SIZE)
79350 	duk_pop_2_nodecref_unsafe(thr);
79351 #else
79352 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -2)));
79353 	DUK_ASSERT(!DUK_TVAL_NEEDS_REFCOUNT_UPDATE(duk_get_tval(thr, -1)));
79354 	DUK_ASSERT(duk_get_top(thr) >= 2);
79355 	thr->valstack_top -= 2;
79356 	tv_x = thr->valstack_top;
79357 	tv_y = tv_x + 1;
79358 	DUK_TVAL_SET_UNDEFINED(tv_x);  /* Value stack policy */
79359 	DUK_TVAL_SET_UNDEFINED(tv_y);
79360 #endif
79361 
79362 	return duk__compare_number(retval, d1, d2);
79363 }
79364 
79365 /*
79366  *  instanceof
79367  */
79368 
79369 /*
79370  *  ES2015 Section 7.3.19 describes the OrdinaryHasInstance() algorithm
79371  *  which covers both bound and non-bound functions; in effect the algorithm
79372  *  includes E5 Sections 11.8.6, 15.3.5.3, and 15.3.4.5.3.
79373  *
79374  *  ES2015 Section 12.9.4 describes the instanceof operator which first
79375  *  checks @@hasInstance well-known symbol and falls back to
79376  *  OrdinaryHasInstance().
79377  *
79378  *  Limited Proxy support: don't support 'getPrototypeOf' trap but
79379  *  continue lookup in Proxy target if the value is a Proxy.
79380  */
79381 
79382 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) {
79383 	duk_hobject *func;
79384 	duk_hobject *val;
79385 	duk_hobject *proto;
79386 	duk_tval *tv;
79387 	duk_bool_t skip_first;
79388 	duk_uint_t sanity;
79389 
79390 	/*
79391 	 *  Get the values onto the stack first.  It would be possible to cover
79392 	 *  some normal cases without resorting to the value stack.
79393 	 *
79394 	 *  The right hand side could be a light function (as they generally
79395 	 *  behave like objects).  Light functions never have a 'prototype'
79396 	 *  property so E5.1 Section 15.3.5.3 step 3 always throws a TypeError.
79397 	 *  Using duk_require_hobject() is thus correct (except for error msg).
79398 	 */
79399 
79400 	duk_push_tval(thr, tv_x);
79401 	duk_push_tval(thr, tv_y);
79402 	func = duk_require_hobject(thr, -1);
79403 	DUK_ASSERT(func != NULL);
79404 
79405 #if defined(DUK_USE_SYMBOL_BUILTIN)
79406 	/*
79407 	 *  @@hasInstance check, ES2015 Section 12.9.4, Steps 2-4.
79408 	 */
79409 	if (!skip_sym_check) {
79410 		if (duk_get_method_stridx(thr, -1, DUK_STRIDX_WELLKNOWN_SYMBOL_HAS_INSTANCE)) {
79411 			/* [ ... lhs rhs func ] */
79412 			duk_insert(thr, -3);    /* -> [ ... func lhs rhs ] */
79413 			duk_swap_top(thr, -2);  /* -> [ ... func rhs(this) lhs ] */
79414 			duk_call_method(thr, 1);
79415 			return duk_to_boolean_top_pop(thr);
79416 		}
79417 	}
79418 #else
79419 	DUK_UNREF(skip_sym_check);
79420 #endif
79421 
79422 	/*
79423 	 *  For bound objects, [[HasInstance]] just calls the target function
79424 	 *  [[HasInstance]].  If that is again a bound object, repeat until
79425 	 *  we find a non-bound Function object.
79426 	 *
79427 	 *  The bound function chain is now "collapsed" so there can be only
79428 	 *  one bound function in the chain.
79429 	 */
79430 
79431 	if (!DUK_HOBJECT_IS_CALLABLE(func)) {
79432 		/*
79433 		 *  Note: of native ECMAScript objects, only Function instances
79434 		 *  have a [[HasInstance]] internal property.  Custom objects might
79435 		 *  also have it, but not in current implementation.
79436 		 *
79437 		 *  XXX: add a separate flag, DUK_HOBJECT_FLAG_ALLOW_INSTANCEOF?
79438 		 */
79439 		goto error_invalid_rval;
79440 	}
79441 
79442 	if (DUK_HOBJECT_HAS_BOUNDFUNC(func)) {
79443 		duk_push_tval(thr, &((duk_hboundfunc *) (void *) func)->target);
79444 		duk_replace(thr, -2);
79445 		func = duk_require_hobject(thr, -1);  /* lightfunc throws */
79446 
79447 		/* Rely on Function.prototype.bind() never creating bound
79448 		 * functions whose target is not proper.
79449 		 */
79450 		DUK_ASSERT(func != NULL);
79451 		DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
79452 	}
79453 
79454 	/*
79455 	 *  'func' is now a non-bound object which supports [[HasInstance]]
79456 	 *  (which here just means DUK_HOBJECT_FLAG_CALLABLE).  Move on
79457 	 *  to execute E5 Section 15.3.5.3.
79458 	 */
79459 
79460 	DUK_ASSERT(func != NULL);
79461 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));
79462 	DUK_ASSERT(DUK_HOBJECT_IS_CALLABLE(func));
79463 
79464 	/* [ ... lval rval(func) ] */
79465 
79466 	/* For lightfuncs, buffers, and pointers start the comparison directly
79467 	 * from the virtual prototype object.
79468 	 */
79469 	skip_first = 0;
79470 	tv = DUK_GET_TVAL_NEGIDX(thr, -2);
79471 	switch (DUK_TVAL_GET_TAG(tv)) {
79472 	case DUK_TAG_LIGHTFUNC:
79473 		val = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
79474 		DUK_ASSERT(val != NULL);
79475 		break;
79476 	case DUK_TAG_BUFFER:
79477 		val = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
79478 		DUK_ASSERT(val != NULL);
79479 		break;
79480 	case DUK_TAG_POINTER:
79481 		val = thr->builtins[DUK_BIDX_POINTER_PROTOTYPE];
79482 		DUK_ASSERT(val != NULL);
79483 		break;
79484 	case DUK_TAG_OBJECT:
79485 		skip_first = 1;  /* Ignore object itself on first round. */
79486 		val = DUK_TVAL_GET_OBJECT(tv);
79487 		DUK_ASSERT(val != NULL);
79488 		break;
79489 	default:
79490 		goto pop2_and_false;
79491 	}
79492 	DUK_ASSERT(val != NULL);  /* Loop doesn't actually rely on this. */
79493 
79494 	/* Look up .prototype of rval.  Leave it on the value stack in case it
79495 	 * has been virtualized (e.g. getter, Proxy trap).
79496 	 */
79497 	duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_PROTOTYPE);  /* -> [ ... lval rval rval.prototype ] */
79498 #if defined(DUK_USE_VERBOSE_ERRORS)
79499 	proto = duk_get_hobject(thr, -1);
79500 	if (proto == NULL) {
79501 		goto error_invalid_rval_noproto;
79502 	}
79503 #else
79504 	proto = duk_require_hobject(thr, -1);
79505 #endif
79506 
79507 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
79508 	do {
79509 		/*
79510 		 *  Note: prototype chain is followed BEFORE first comparison.  This
79511 		 *  means that the instanceof lval is never itself compared to the
79512 		 *  rval.prototype property.  This is apparently intentional, see E5
79513 		 *  Section 15.3.5.3, step 4.a.
79514 		 *
79515 		 *  Also note:
79516 		 *
79517 		 *      js> (function() {}) instanceof Function
79518 		 *      true
79519 		 *      js> Function instanceof Function
79520 		 *      true
79521 		 *
79522 		 *  For the latter, h_proto will be Function.prototype, which is the
79523 		 *  built-in Function prototype.  Because Function.[[Prototype]] is
79524 		 *  also the built-in Function prototype, the result is true.
79525 		 */
79526 
79527 		if (!val) {
79528 			goto pop3_and_false;
79529 		}
79530 
79531 		DUK_ASSERT(val != NULL);
79532 #if defined(DUK_USE_ES6_PROXY)
79533 		val = duk_hobject_resolve_proxy_target(val);
79534 #endif
79535 
79536 		if (skip_first) {
79537 			skip_first = 0;
79538 		} else if (val == proto) {
79539 			goto pop3_and_true;
79540 		}
79541 
79542 		DUK_ASSERT(val != NULL);
79543 		val = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, val);
79544 	} while (--sanity > 0);
79545 
79546 	if (DUK_UNLIKELY(sanity == 0)) {
79547 		DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
79548 		DUK_WO_NORETURN(return 0;);
79549 	}
79550 	DUK_UNREACHABLE();
79551 
79552  pop2_and_false:
79553 	duk_pop_2_unsafe(thr);
79554 	return 0;
79555 
79556  pop3_and_false:
79557 	duk_pop_3_unsafe(thr);
79558 	return 0;
79559 
79560  pop3_and_true:
79561 	duk_pop_3_unsafe(thr);
79562 	return 1;
79563 
79564  error_invalid_rval:
79565 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL);
79566 	DUK_WO_NORETURN(return 0;);
79567 
79568 #if defined(DUK_USE_VERBOSE_ERRORS)
79569  error_invalid_rval_noproto:
79570 	DUK_ERROR_TYPE(thr, DUK_STR_INVALID_INSTANCEOF_RVAL_NOPROTO);
79571 	DUK_WO_NORETURN(return 0;);
79572 #endif
79573 }
79574 
79575 #if defined(DUK_USE_SYMBOL_BUILTIN)
79576 DUK_INTERNAL duk_bool_t duk_js_instanceof_ordinary(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79577 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 1 /*skip_sym_check*/);
79578 }
79579 #endif
79580 
79581 DUK_INTERNAL duk_bool_t duk_js_instanceof(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79582 	return duk__js_instanceof_helper(thr, tv_x, tv_y, 0 /*skip_sym_check*/);
79583 }
79584 
79585 /*
79586  *  in
79587  */
79588 
79589 /*
79590  *  E5 Sections 11.8.7, 8.12.6.
79591  *
79592  *  Basically just a property existence check using [[HasProperty]].
79593  */
79594 
79595 DUK_INTERNAL duk_bool_t duk_js_in(duk_hthread *thr, duk_tval *tv_x, duk_tval *tv_y) {
79596 	duk_bool_t retval;
79597 
79598 	/*
79599 	 *  Get the values onto the stack first.  It would be possible to cover
79600 	 *  some normal cases without resorting to the value stack (e.g. if
79601 	 *  lval is already a string).
79602 	 */
79603 
79604 	/* XXX: The ES5/5.1/6 specifications require that the key in 'key in obj'
79605 	 * must be string coerced before the internal HasProperty() algorithm is
79606 	 * invoked.  A fast path skipping coercion could be safely implemented for
79607 	 * numbers (as number-to-string coercion has no side effects).  For ES2015
79608 	 * proxy behavior, the trap 'key' argument must be in a string coerced
79609 	 * form (which is a shame).
79610 	 */
79611 
79612 	/* TypeError if rval is not an object or object like (e.g. lightfunc
79613 	 * or plain buffer).
79614 	 */
79615 	duk_push_tval(thr, tv_x);
79616 	duk_push_tval(thr, tv_y);
79617 	duk_require_type_mask(thr, -1, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
79618 
79619 	(void) duk_to_property_key_hstring(thr, -2);
79620 
79621 	retval = duk_hobject_hasprop(thr,
79622 	                             DUK_GET_TVAL_NEGIDX(thr, -1),
79623 	                             DUK_GET_TVAL_NEGIDX(thr, -2));
79624 
79625 	duk_pop_2_unsafe(thr);
79626 	return retval;
79627 }
79628 
79629 /*
79630  *  typeof
79631  *
79632  *  E5 Section 11.4.3.
79633  *
79634  *  Very straightforward.  The only question is what to return for our
79635  *  non-standard tag / object types.
79636  *
79637  *  There is an unfortunate string constant define naming problem with
79638  *  typeof return values for e.g. "Object" and "object"; careful with
79639  *  the built-in string defines.  The LC_XXX defines are used for the
79640  *  lowercase variants now.
79641  */
79642 
79643 DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
79644 	duk_small_uint_t stridx = 0;
79645 
79646 	switch (DUK_TVAL_GET_TAG(tv_x)) {
79647 	case DUK_TAG_UNDEFINED: {
79648 		stridx = DUK_STRIDX_LC_UNDEFINED;
79649 		break;
79650 	}
79651 	case DUK_TAG_NULL: {
79652 		/* Note: not a typo, "object" is returned for a null value. */
79653 		stridx = DUK_STRIDX_LC_OBJECT;
79654 		break;
79655 	}
79656 	case DUK_TAG_BOOLEAN: {
79657 		stridx = DUK_STRIDX_LC_BOOLEAN;
79658 		break;
79659 	}
79660 	case DUK_TAG_POINTER: {
79661 		/* Implementation specific. */
79662 		stridx = DUK_STRIDX_LC_POINTER;
79663 		break;
79664 	}
79665 	case DUK_TAG_STRING: {
79666 		duk_hstring *str;
79667 
79668 		/* All internal keys are identified as Symbols. */
79669 		str = DUK_TVAL_GET_STRING(tv_x);
79670 		DUK_ASSERT(str != NULL);
79671 		if (DUK_UNLIKELY(DUK_HSTRING_HAS_SYMBOL(str))) {
79672 			stridx = DUK_STRIDX_LC_SYMBOL;
79673 		} else {
79674 			stridx = DUK_STRIDX_LC_STRING;
79675 		}
79676 		break;
79677 	}
79678 	case DUK_TAG_OBJECT: {
79679 		duk_hobject *obj = DUK_TVAL_GET_OBJECT(tv_x);
79680 		DUK_ASSERT(obj != NULL);
79681 		if (DUK_HOBJECT_IS_CALLABLE(obj)) {
79682 			stridx = DUK_STRIDX_LC_FUNCTION;
79683 		} else {
79684 			stridx = DUK_STRIDX_LC_OBJECT;
79685 		}
79686 		break;
79687 	}
79688 	case DUK_TAG_BUFFER: {
79689 		/* Implementation specific.  In Duktape 1.x this would be
79690 		 * 'buffer', in Duktape 2.x changed to 'object' because plain
79691 		 * buffers now mimic Uint8Array objects.
79692 		 */
79693 		stridx = DUK_STRIDX_LC_OBJECT;
79694 		break;
79695 	}
79696 	case DUK_TAG_LIGHTFUNC: {
79697 		stridx = DUK_STRIDX_LC_FUNCTION;
79698 		break;
79699 	}
79700 #if defined(DUK_USE_FASTINT)
79701 	case DUK_TAG_FASTINT:
79702 #endif
79703 	default: {
79704 		/* number */
79705 		DUK_ASSERT(!DUK_TVAL_IS_UNUSED(tv_x));
79706 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv_x));
79707 		stridx = DUK_STRIDX_LC_NUMBER;
79708 		break;
79709 	}
79710 	}
79711 
79712 	DUK_ASSERT_STRIDX_VALID(stridx);
79713 	return stridx;
79714 }
79715 
79716 /*
79717  *  Array index and length
79718  *
79719  *  Array index: E5 Section 15.4
79720  *  Array length: E5 Section 15.4.5.1 steps 3.c - 3.d (array length write)
79721  */
79722 
79723 /* Compure array index from string context, or return a "not array index"
79724  * indicator.
79725  */
79726 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string(const duk_uint8_t *str, duk_uint32_t blen) {
79727 	duk_uarridx_t res;
79728 
79729 	/* Only strings with byte length 1-10 can be 32-bit array indices.
79730 	 * Leading zeroes (except '0' alone), plus/minus signs are not allowed.
79731 	 * We could do a lot of prechecks here, but since most strings won't
79732 	 * start with any digits, it's simpler to just parse the number and
79733 	 * fail quickly.
79734 	 */
79735 
79736 	res = 0;
79737 	if (blen == 0) {
79738 		goto parse_fail;
79739 	}
79740 	do {
79741 		duk_uarridx_t dig;
79742 		dig = (duk_uarridx_t) (*str++) - DUK_ASC_0;
79743 
79744 		if (dig <= 9U) {
79745 			/* Careful overflow handling.  When multiplying by 10:
79746 			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
79747 			 *   0...9 is safe.
79748 			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
79749 			 *   0...5 is safe, 6...9 overflows.
79750 			 * - 0x1999999a x 10 = 0x100000004: always overflow.
79751 			 */
79752 			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
79753 				if (res >= 0x1999999aUL) {
79754 					/* Always overflow. */
79755 					goto parse_fail;
79756 				}
79757 				DUK_ASSERT(res == 0x19999999UL);
79758 				if (dig >= 6U) {
79759 					goto parse_fail;
79760 				}
79761 				res = 0xfffffffaUL + dig;
79762 				DUK_ASSERT(res >= 0xfffffffaUL);
79763 				DUK_ASSERT_DISABLE(res <= 0xffffffffUL);  /* range */
79764 			} else {
79765 				res = res * 10U + dig;
79766 				if (DUK_UNLIKELY(res == 0)) {
79767 					/* If 'res' is 0, previous 'res' must
79768 					 * have been 0 and we scanned in a zero.
79769 					 * This is only allowed if blen == 1,
79770 					 * i.e. the exact string '0'.
79771 					 */
79772 					if (blen == (duk_uint32_t) 1) {
79773 						return 0;
79774 					}
79775 					goto parse_fail;
79776 				}
79777 			}
79778 		} else {
79779 			/* Because 'dig' is unsigned, catches both values
79780 			 * above '9' and below '0'.
79781 			 */
79782 			goto parse_fail;
79783 		}
79784 	} while (--blen > 0);
79785 
79786 	return res;
79787 
79788  parse_fail:
79789 	return DUK_HSTRING_NO_ARRAY_INDEX;
79790 }
79791 
79792 #if !defined(DUK_USE_HSTRING_ARRIDX)
79793 /* Get array index for a string which is known to be an array index.  This helper
79794  * is needed when duk_hstring doesn't concretely store the array index, but strings
79795  * are flagged as array indices at intern time.
79796  */
79797 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast_known(duk_hstring *h) {
79798 	const duk_uint8_t *p;
79799 	duk_uarridx_t res;
79800 	duk_uint8_t t;
79801 
79802 	DUK_ASSERT(h != NULL);
79803 	DUK_ASSERT(DUK_HSTRING_HAS_ARRIDX(h));
79804 
79805 	p = DUK_HSTRING_GET_DATA(h);
79806 	res = 0;
79807 	for (;;) {
79808 		t = *p++;
79809 		if (DUK_UNLIKELY(t == 0)) {
79810 			/* Scanning to NUL is always safe for interned strings. */
79811 			break;
79812 		}
79813 		DUK_ASSERT(t >= (duk_uint8_t) DUK_ASC_0 && t <= (duk_uint8_t) DUK_ASC_9);
79814 		res = res * 10U + (duk_uarridx_t) t - (duk_uarridx_t) DUK_ASC_0;
79815 	}
79816 	return res;
79817 }
79818 
79819 DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_hstring_fast(duk_hstring *h) {
79820 	DUK_ASSERT(h != NULL);
79821 	if (!DUK_HSTRING_HAS_ARRIDX(h)) {
79822 		return DUK_HSTRING_NO_ARRAY_INDEX;
79823 	}
79824 	return duk_js_to_arrayindex_hstring_fast_known(h);
79825 }
79826 #endif  /* DUK_USE_HSTRING_ARRIDX */
79827 #line 1 "duk_js_var.c"
79828 /*
79829  *  Identifier access and function closure handling.
79830  *
79831  *  Provides the primitives for slow path identifier accesses: GETVAR,
79832  *  PUTVAR, DELVAR, etc.  The fast path, direct register accesses, should
79833  *  be used for most identifier accesses.  Consequently, these slow path
79834  *  primitives should be optimized for maximum compactness.
79835  *
79836  *  ECMAScript environment records (declarative and object) are represented
79837  *  as internal objects with control keys.  Environment records have a
79838  *  parent record ("outer environment reference") which is represented by
79839  *  the implicit prototype for technical reasons (in other words, it is a
79840  *  convenient field).  The prototype chain is not followed in the ordinary
79841  *  sense for variable lookups.
79842  *
79843  *  See identifier-handling.rst for more details on the identifier algorithms
79844  *  and the internal representation.  See function-objects.rst for details on
79845  *  what function templates and instances are expected to look like.
79846  *
79847  *  Care must be taken to avoid duk_tval pointer invalidation caused by
79848  *  e.g. value stack or object resizing.
79849  *
79850  *  TODO: properties for function instances could be initialized much more
79851  *  efficiently by creating a property allocation for a certain size and
79852  *  filling in keys and values directly (and INCREFing both with "bulk incref"
79853  *  primitives.
79854  *
79855  *  XXX: duk_hobject_getprop() and duk_hobject_putprop() calls are a bit
79856  *  awkward (especially because they follow the prototype chain); rework
79857  *  if "raw" own property helpers are added.
79858  */
79859 
79860 /* #include duk_internal.h -> already included */
79861 
79862 /*
79863  *  Local result type for duk__get_identifier_reference() lookup.
79864  */
79865 
79866 typedef struct {
79867 	duk_hobject *env;
79868 	duk_hobject *holder;      /* for object-bound identifiers */
79869 	duk_tval *value;          /* for register-bound and declarative env identifiers */
79870 	duk_uint_t attrs;         /* property attributes for identifier (relevant if value != NULL) */
79871 	duk_bool_t has_this;      /* for object-bound identifiers: provide 'this' binding */
79872 } duk__id_lookup_result;
79873 
79874 /*
79875  *  Create a new function object based on a "template function" which contains
79876  *  compiled bytecode, constants, etc, but lacks a lexical environment.
79877  *
79878  *  ECMAScript requires that each created closure is a separate object, with
79879  *  its own set of editable properties.  However, structured property values
79880  *  (such as the formal arguments list and the variable map) are shared.
79881  *  Also the bytecode, constants, and inner functions are shared.
79882  *
79883  *  See E5 Section 13.2 for detailed requirements on the function objects;
79884  *  there are no similar requirements for function "templates" which are an
79885  *  implementation dependent internal feature.  Also see function-objects.rst
79886  *  for a discussion on the function instance properties provided by this
79887  *  implementation.
79888  *
79889  *  Notes:
79890  *
79891  *   * Order of internal properties should match frequency of use, since the
79892  *     properties will be linearly scanned on lookup (functions usually don't
79893  *     have enough properties to warrant a hash part).
79894  *
79895  *   * The created closure is independent of its template; they do share the
79896  *     same 'data' buffer object, but the template object itself can be freed
79897  *     even if the closure object remains reachable.
79898  */
79899 
79900 DUK_LOCAL void duk__inc_data_inner_refcounts(duk_hthread *thr, duk_hcompfunc *f) {
79901 	duk_tval *tv, *tv_end;
79902 	duk_hobject **funcs, **funcs_end;
79903 
79904 	DUK_UNREF(thr);
79905 
79906 	/* If function creation fails due to out-of-memory, the data buffer
79907 	 * pointer may be NULL in some cases.  That's actually possible for
79908 	 * GC code, but shouldn't be possible here because the incomplete
79909 	 * function will be unwound from the value stack and never instantiated.
79910 	 */
79911 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, f) != NULL);
79912 
79913 	tv = DUK_HCOMPFUNC_GET_CONSTS_BASE(thr->heap, f);
79914 	tv_end = DUK_HCOMPFUNC_GET_CONSTS_END(thr->heap, f);
79915 	while (tv < tv_end) {
79916 		DUK_TVAL_INCREF(thr, tv);
79917 		tv++;
79918 	}
79919 
79920 	funcs = DUK_HCOMPFUNC_GET_FUNCS_BASE(thr->heap, f);
79921 	funcs_end = DUK_HCOMPFUNC_GET_FUNCS_END(thr->heap, f);
79922 	while (funcs < funcs_end) {
79923 		DUK_HEAPHDR_INCREF(thr, (duk_heaphdr *) *funcs);
79924 		funcs++;
79925 	}
79926 }
79927 
79928 /* Push a new closure on the stack.
79929  *
79930  * Note: if fun_temp has NEWENV, i.e. a new lexical and variable declaration
79931  * is created when the function is called, only outer_lex_env matters
79932  * (outer_var_env is ignored and may or may not be same as outer_lex_env).
79933  */
79934 
79935 DUK_LOCAL const duk_uint16_t duk__closure_copy_proplist[] = {
79936 	/* order: most frequent to least frequent */
79937 	DUK_STRIDX_INT_VARMAP,
79938 	DUK_STRIDX_INT_FORMALS,
79939 #if defined(DUK_USE_PC2LINE)
79940 	DUK_STRIDX_INT_PC2LINE,
79941 #endif
79942 #if defined(DUK_USE_FUNC_FILENAME_PROPERTY)
79943 	DUK_STRIDX_FILE_NAME,
79944 #endif
79945 #if defined(DUK_USE_NONSTD_FUNC_SOURCE_PROPERTY)
79946 	DUK_STRIDX_INT_SOURCE
79947 #endif
79948 };
79949 
79950 DUK_INTERNAL
79951 void duk_js_push_closure(duk_hthread *thr,
79952                          duk_hcompfunc *fun_temp,
79953                          duk_hobject *outer_var_env,
79954                          duk_hobject *outer_lex_env,
79955                          duk_bool_t add_auto_proto) {
79956 	duk_hcompfunc *fun_clos;
79957 	duk_small_uint_t i;
79958 	duk_uint_t len_value;
79959 
79960 	DUK_ASSERT(fun_temp != NULL);
79961 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp) != NULL);
79962 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp) != NULL);
79963 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp) != NULL);
79964 	DUK_ASSERT(outer_var_env != NULL);
79965 	DUK_ASSERT(outer_lex_env != NULL);
79966 	DUK_UNREF(len_value);
79967 
79968 	fun_clos = duk_push_hcompfunc(thr);
79969 	DUK_ASSERT(fun_clos != NULL);
79970 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) fun_clos) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
79971 
79972 	duk_push_hobject(thr, &fun_temp->obj);  /* -> [ ... closure template ] */
79973 
79974 	DUK_ASSERT(DUK_HOBJECT_IS_COMPFUNC((duk_hobject *) fun_clos));
79975 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) == NULL);
79976 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) == NULL);
79977 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) == NULL);
79978 
79979 	DUK_HCOMPFUNC_SET_DATA(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_temp));
79980 	DUK_HCOMPFUNC_SET_FUNCS(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_temp));
79981 	DUK_HCOMPFUNC_SET_BYTECODE(thr->heap, fun_clos, DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_temp));
79982 
79983 	/* Note: all references inside 'data' need to get their refcounts
79984 	 * upped too.  This is the case because refcounts are decreased
79985 	 * through every function referencing 'data' independently.
79986 	 */
79987 
79988 	DUK_HBUFFER_INCREF(thr, DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos));
79989 	duk__inc_data_inner_refcounts(thr, fun_temp);
79990 
79991 	fun_clos->nregs = fun_temp->nregs;
79992 	fun_clos->nargs = fun_temp->nargs;
79993 #if defined(DUK_USE_DEBUGGER_SUPPORT)
79994 	fun_clos->start_line = fun_temp->start_line;
79995 	fun_clos->end_line = fun_temp->end_line;
79996 #endif
79997 
79998 	DUK_ASSERT(DUK_HCOMPFUNC_GET_DATA(thr->heap, fun_clos) != NULL);
79999 	DUK_ASSERT(DUK_HCOMPFUNC_GET_FUNCS(thr->heap, fun_clos) != NULL);
80000 	DUK_ASSERT(DUK_HCOMPFUNC_GET_BYTECODE(thr->heap, fun_clos) != NULL);
80001 
80002 	/* XXX: Could also copy from template, but there's no way to have any
80003 	 * other value here now (used code has no access to the template).
80004 	 * Prototype is set by duk_push_hcompfunc().
80005 	 */
80006 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80007 #if 0
80008 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, &fun_clos->obj, thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80009 #endif
80010 
80011 	/* Copy duk_hobject flags as is from the template using a mask.
80012 	 * Leave out duk_heaphdr owned flags just in case (e.g. if there's
80013 	 * some GC flag or similar).  Some flags can then be adjusted
80014 	 * separately if necessary.
80015 	 */
80016 
80017 	/* DUK_HEAPHDR_SET_FLAGS() masks changes to non-duk_heaphdr flags only. */
80018 	DUK_HEAPHDR_SET_FLAGS((duk_heaphdr *) fun_clos, DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp));
80019 	DUK_DD(DUK_DDPRINT("fun_temp heaphdr flags: 0x%08lx, fun_clos heaphdr flags: 0x%08lx",
80020 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_temp),
80021 	                   (unsigned long) DUK_HEAPHDR_GET_FLAGS_RAW((duk_heaphdr *) fun_clos)));
80022 
80023 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80024 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(&fun_clos->obj));
80025 	DUK_ASSERT(DUK_HOBJECT_HAS_COMPFUNC(&fun_clos->obj));
80026 	DUK_ASSERT(!DUK_HOBJECT_HAS_NATFUNC(&fun_clos->obj));
80027 	DUK_ASSERT(!DUK_HOBJECT_IS_THREAD(&fun_clos->obj));
80028 	/* DUK_HOBJECT_FLAG_ARRAY_PART: don't care */
80029 	/* DUK_HOBJECT_FLAG_NEWENV: handled below */
80030 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(&fun_clos->obj));
80031 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_STRINGOBJ(&fun_clos->obj));
80032 	DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARGUMENTS(&fun_clos->obj));
80033 
80034 	if (!DUK_HOBJECT_HAS_CONSTRUCTABLE(&fun_clos->obj)) {
80035 		/* If the template is not constructable don't add an automatic
80036 		 * .prototype property.  This is the case for e.g. ES2015 object
80037 		 * literal getters/setters and method definitions.
80038 		 */
80039 		add_auto_proto = 0;
80040 	}
80041 
80042 	/*
80043 	 *  Setup environment record properties based on the template and
80044 	 *  its flags.
80045 	 *
80046 	 *  If DUK_HOBJECT_HAS_NEWENV(fun_temp) is true, the environment
80047 	 *  records represent identifiers "outside" the function; the
80048 	 *  "inner" environment records are created on demand.  Otherwise,
80049 	 *  the environment records are those that will be directly used
80050 	 *  (e.g. for declarations).
80051 	 *
80052 	 *  _Lexenv is always set; _Varenv defaults to _Lexenv if missing,
80053 	 *  so _Varenv is only set if _Lexenv != _Varenv.
80054 	 *
80055 	 *  This is relatively complex, see doc/identifier-handling.rst.
80056 	 */
80057 
80058 	if (DUK_HOBJECT_HAS_NEWENV(&fun_clos->obj)) {
80059 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80060 		if (DUK_HOBJECT_HAS_NAMEBINDING(&fun_clos->obj)) {
80061 			duk_hobject *proto;
80062 			duk_hdecenv *new_env;
80063 
80064 			/*
80065 			 *  Named function expression, name needs to be bound
80066 			 *  in an intermediate environment record.  The "outer"
80067 			 *  lexical/variable environment will thus be:
80068 			 *
80069 			 *  a) { funcname: <func>, __prototype: outer_lex_env }
80070 			 *  b) { funcname: <func>, __prototype:  <globalenv> }  (if outer_lex_env missing)
80071 			 */
80072 
80073 			if (outer_lex_env) {
80074 				proto = outer_lex_env;
80075 			} else {
80076 				proto = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80077 			}
80078 
80079 			/* -> [ ... closure template env ] */
80080 			new_env = duk_hdecenv_alloc(thr,
80081 			                            DUK_HOBJECT_FLAG_EXTENSIBLE |
80082 			                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
80083 			DUK_ASSERT(new_env != NULL);
80084 			duk_push_hobject(thr, (duk_hobject *) new_env);
80085 
80086 			DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) new_env) == NULL);
80087 			DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) new_env, proto);
80088 			DUK_HOBJECT_INCREF_ALLOWNULL(thr, proto);
80089 
80090 			DUK_ASSERT(new_env->thread == NULL);  /* Closed. */
80091 			DUK_ASSERT(new_env->varmap == NULL);
80092 
80093 			/* It's important that duk_xdef_prop() is a 'raw define' so that any
80094 			 * properties in an ancestor are never an issue (they should never be
80095 			 * e.g. non-writable, but just in case).
80096 			 *
80097 			 * Because template objects are not visible to user code, the case
80098 			 * where .name is missing shouldn't happen in practice.  It it does,
80099 			 * the name 'undefined' gets bound and maps to the closure (which is
80100 			 * a bit odd, but safe).
80101 			 */
80102 			(void) duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_NAME);
80103 			/* -> [ ... closure template env funcname ] */
80104 			duk_dup_m4(thr);                                           /* -> [ ... closure template env funcname closure ] */
80105 			duk_xdef_prop(thr, -3, DUK_PROPDESC_FLAGS_NONE);           /* -> [ ... closure template env ] */
80106 			/* env[funcname] = closure */
80107 
80108 			/* [ ... closure template env ] */
80109 
80110 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80111 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, (duk_hobject *) new_env);
80112 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80113 			DUK_HOBJECT_INCREF(thr, (duk_hobject *) new_env);
80114 			duk_pop_unsafe(thr);
80115 
80116 			/* [ ... closure template ] */
80117 		}
80118 		else
80119 #endif  /* DUK_USE_FUNC_NAME_PROPERTY */
80120 		{
80121 			/*
80122 			 *  Other cases (function declaration, anonymous function expression,
80123 			 *  strict direct eval code).  The "outer" environment will be whatever
80124 			 *  the caller gave us.
80125 			 */
80126 
80127 			DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80128 			DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_lex_env);
80129 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80130 			DUK_HOBJECT_INCREF(thr, outer_lex_env);
80131 
80132 			/* [ ... closure template ] */
80133 		}
80134 	} else {
80135 		/*
80136 		 *  Function gets no new environment when called.  This is the
80137 		 *  case for global code, indirect eval code, and non-strict
80138 		 *  direct eval code.  There is no direct correspondence to the
80139 		 *  E5 specification, as global/eval code is not exposed as a
80140 		 *  function.
80141 		 */
80142 
80143 		DUK_ASSERT(!DUK_HOBJECT_HAS_NAMEBINDING(&fun_temp->obj));
80144 
80145 		DUK_HCOMPFUNC_SET_LEXENV(thr->heap, fun_clos, outer_lex_env);
80146 		DUK_HCOMPFUNC_SET_VARENV(thr->heap, fun_clos, outer_var_env);
80147 		DUK_HOBJECT_INCREF(thr, outer_lex_env);  /* NULLs not allowed; asserted on entry */
80148 		DUK_HOBJECT_INCREF(thr, outer_var_env);
80149 	}
80150 	DUK_DDD(DUK_DDDPRINT("closure varenv -> %!ipO, lexenv -> %!ipO",
80151 	                     (duk_heaphdr *) fun_clos->var_env,
80152 	                     (duk_heaphdr *) fun_clos->lex_env));
80153 
80154 	/* Call handling assumes this for all callable closures. */
80155 	DUK_ASSERT(DUK_HCOMPFUNC_GET_LEXENV(thr->heap, fun_clos) != NULL);
80156 	DUK_ASSERT(DUK_HCOMPFUNC_GET_VARENV(thr->heap, fun_clos) != NULL);
80157 
80158 	/*
80159 	 *  Copy some internal properties directly
80160 	 *
80161 	 *  The properties will be non-writable and non-enumerable, but
80162 	 *  configurable.
80163 	 */
80164 
80165 	/* [ ... closure template ] */
80166 
80167 	DUK_DDD(DUK_DDDPRINT("copying properties: closure=%!iT, template=%!iT",
80168 	                     (duk_tval *) duk_get_tval(thr, -2),
80169 	                     (duk_tval *) duk_get_tval(thr, -1)));
80170 
80171 	for (i = 0; i < (duk_small_uint_t) (sizeof(duk__closure_copy_proplist) / sizeof(duk_uint16_t)); i++) {
80172 		duk_small_int_t stridx = (duk_small_int_t) duk__closure_copy_proplist[i];
80173 		if (duk_get_prop_stridx_short(thr, -1, stridx)) {
80174 			/* [ ... closure template val ] */
80175 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> found", (long) stridx));
80176 			duk_xdef_prop_stridx_short(thr, -3, stridx, DUK_PROPDESC_FLAGS_C);
80177 		} else {
80178 			DUK_DDD(DUK_DDDPRINT("copying property, stridx=%ld -> not found", (long) stridx));
80179 			duk_pop_unsafe(thr);
80180 		}
80181 	}
80182 
80183 	/*
80184 	 *  "length" maps to number of formals (E5 Section 13.2) for function
80185 	 *  declarations/expressions (non-bound functions).  Note that 'nargs'
80186 	 *  is NOT necessarily equal to the number of arguments.  Use length
80187 	 *  of _Formals; if missing, assume nargs matches .length.
80188 	 */
80189 
80190 	/* [ ... closure template ] */
80191 
80192 	/* XXX: these lookups should be just own property lookups instead of
80193 	 * looking up the inheritance chain.
80194 	 */
80195 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_INT_FORMALS)) {
80196 		/* [ ... closure template formals ] */
80197 		len_value = (duk_uint_t) duk_get_length(thr, -1);  /* could access duk_harray directly, not important */
80198 		DUK_DD(DUK_DDPRINT("closure length from _Formals -> %ld", (long) len_value));
80199 	} else {
80200 		len_value = fun_temp->nargs;
80201 		DUK_DD(DUK_DDPRINT("closure length defaulted from nargs -> %ld", (long) len_value));
80202 	}
80203 	duk_pop_unsafe(thr);
80204 
80205 	duk_push_uint(thr, len_value);  /* [ ... closure template len_value ] */
80206 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_C);
80207 
80208 	/*
80209 	 *  "prototype" is, by default, a fresh object with the "constructor"
80210 	 *  property.
80211 	 *
80212 	 *  Note that this creates a circular reference for every function
80213 	 *  instance (closure) which prevents refcount-based collection of
80214 	 *  function instances.
80215 	 *
80216 	 *  XXX: Try to avoid creating the default prototype object, because
80217 	 *  many functions are not used as constructors and the default
80218 	 *  prototype is unnecessary.  Perhaps it could be created on-demand
80219 	 *  when it is first accessed?
80220 	 */
80221 
80222 	/* [ ... closure template ] */
80223 
80224 	if (add_auto_proto) {
80225 		duk_push_object(thr);  /* -> [ ... closure template newobj ] */
80226 		duk_dup_m3(thr);       /* -> [ ... closure template newobj closure ] */
80227 		duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_CONSTRUCTOR, DUK_PROPDESC_FLAGS_WC);  /* -> [ ... closure template newobj ] */
80228 		duk_compact(thr, -1);  /* compact the prototype */
80229 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_PROTOTYPE, DUK_PROPDESC_FLAGS_W);     /* -> [ ... closure template ] */
80230 	}
80231 
80232 	/*
80233 	 *  "arguments" and "caller" must be mapped to throwers for strict
80234 	 *  mode and bound functions (E5 Section 15.3.5).
80235 	 *
80236 	 *  XXX: This is expensive to have for every strict function instance.
80237 	 *  Try to implement as virtual properties or on-demand created properties.
80238 	 */
80239 
80240 	/* [ ... closure template ] */
80241 
80242 	if (DUK_HOBJECT_HAS_STRICT(&fun_clos->obj)) {
80243 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_CALLER);
80244 		duk_xdef_prop_stridx_thrower(thr, -2, DUK_STRIDX_LC_ARGUMENTS);
80245 	} else {
80246 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
80247 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property in use, add initial 'null' value"));
80248 		duk_push_null(thr);
80249 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_CALLER, DUK_PROPDESC_FLAGS_NONE);
80250 #else
80251 		DUK_DDD(DUK_DDDPRINT("function is non-strict and non-standard 'caller' property not used"));
80252 #endif
80253 	}
80254 
80255 	/*
80256 	 *  "name" used to be non-standard but is now defined by ES2015.
80257 	 *  In ES2015/ES2016 the .name property is configurable.
80258 	 */
80259 
80260 	/* [ ... closure template ] */
80261 
80262 #if defined(DUK_USE_FUNC_NAME_PROPERTY)
80263 	/* XXX: Look for own property only; doesn't matter much because
80264 	 * templates are bare objects.
80265 	 */
80266 	if (duk_get_prop_stridx_short(thr, -1, DUK_STRIDX_NAME)) {
80267 		/* [ ... closure template name ] */
80268 		DUK_ASSERT(duk_is_string(thr, -1));
80269 		DUK_DD(DUK_DDPRINT("setting function instance name to %!T", duk_get_tval(thr, -1)));
80270 		duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_NAME, DUK_PROPDESC_FLAGS_C);  /* -> [ ... closure template ] */
80271 	} else {
80272 		/* Anonymous functions don't have a .name in ES2015, so don't set
80273 		 * it on the instance either.  The instance will then inherit
80274 		 * it from Function.prototype.name.
80275 		 */
80276 		DUK_DD(DUK_DDPRINT("not setting function instance .name"));
80277 		duk_pop_unsafe(thr);
80278 	}
80279 #endif
80280 
80281 	/*
80282 	 *  Compact the closure, in most cases no properties will be added later.
80283 	 *  Also, without this the closures end up having unused property slots
80284 	 *  (e.g. in Duktape 0.9.0, 8 slots would be allocated and only 7 used).
80285 	 *  A better future solution would be to allocate the closure directly
80286 	 *  to correct size (and setup the properties directly without going
80287 	 *  through the API).
80288 	 */
80289 
80290 	duk_compact(thr, -2);
80291 
80292 	/*
80293 	 *  Some assertions (E5 Section 13.2).
80294 	 */
80295 
80296 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(&fun_clos->obj) == DUK_HOBJECT_CLASS_FUNCTION);
80297 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, &fun_clos->obj) == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]);
80298 	DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(&fun_clos->obj));
80299 	DUK_ASSERT(duk_has_prop_stridx(thr, -2, DUK_STRIDX_LENGTH) != 0);
80300 	DUK_ASSERT(add_auto_proto == 0 || duk_has_prop_stridx(thr, -2, DUK_STRIDX_PROTOTYPE) != 0);
80301 	/* May be missing .name */
80302 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80303 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_CALLER) != 0);
80304 	DUK_ASSERT(!DUK_HOBJECT_HAS_STRICT(&fun_clos->obj) ||
80305 	           duk_has_prop_stridx(thr, -2, DUK_STRIDX_LC_ARGUMENTS) != 0);
80306 
80307 	/*
80308 	 *  Finish
80309 	 */
80310 
80311 	/* [ ... closure template ] */
80312 
80313 	DUK_DDD(DUK_DDDPRINT("created function instance: template=%!iT -> closure=%!iT",
80314 	                     (duk_tval *) duk_get_tval(thr, -1),
80315 	                     (duk_tval *) duk_get_tval(thr, -2)));
80316 
80317 	duk_pop_unsafe(thr);
80318 
80319 	/* [ ... closure ] */
80320 }
80321 
80322 /*
80323  *  Delayed activation environment record initialization (for functions
80324  *  with NEWENV).
80325  *
80326  *  The non-delayed initialization is handled by duk_handle_call().
80327  */
80328 
80329 /* shared helper */
80330 DUK_INTERNAL
80331 duk_hobject *duk_create_activation_environment_record(duk_hthread *thr,
80332                                                       duk_hobject *func,
80333                                                       duk_size_t bottom_byteoff) {
80334 	duk_hdecenv *env;
80335 	duk_hobject *parent;
80336 	duk_hcompfunc *f;
80337 
80338 	DUK_ASSERT(thr != NULL);
80339 	DUK_ASSERT(func != NULL);
80340 
80341 	f = (duk_hcompfunc *) func;
80342 	parent = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
80343 	if (!parent) {
80344 		parent = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80345 	}
80346 
80347 	env = duk_hdecenv_alloc(thr,
80348 	                        DUK_HOBJECT_FLAG_EXTENSIBLE |
80349 	                        DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_DECENV));
80350 	DUK_ASSERT(env != NULL);
80351 	duk_push_hobject(thr, (duk_hobject *) env);
80352 
80353 	DUK_ASSERT(DUK_HOBJECT_GET_PROTOTYPE(thr->heap, (duk_hobject *) env) == NULL);
80354 	DUK_HOBJECT_SET_PROTOTYPE(thr->heap, (duk_hobject *) env, parent);
80355 	DUK_HOBJECT_INCREF_ALLOWNULL(thr, parent);  /* parent env is the prototype */
80356 
80357 	/* open scope information, for compiled functions only */
80358 
80359 	DUK_ASSERT(env->thread == NULL);
80360 	DUK_ASSERT(env->varmap == NULL);
80361 	DUK_ASSERT(env->regbase_byteoff == 0);
80362 	if (DUK_HOBJECT_IS_COMPFUNC(func)) {
80363 		duk_hobject *varmap;
80364 		duk_tval *tv;
80365 
80366 		tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
80367 		if (tv != NULL && DUK_TVAL_IS_OBJECT(tv)) {
80368 			DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
80369 			varmap = DUK_TVAL_GET_OBJECT(tv);
80370 			DUK_ASSERT(varmap != NULL);
80371 			env->varmap = varmap;
80372 			DUK_HOBJECT_INCREF(thr, varmap);
80373 			env->thread = thr;
80374 			DUK_HTHREAD_INCREF(thr, thr);
80375 			env->regbase_byteoff = bottom_byteoff;
80376 		} else {
80377 			/* If function has no _Varmap, leave the environment closed. */
80378 			DUK_ASSERT(env->thread == NULL);
80379 			DUK_ASSERT(env->varmap == NULL);
80380 			DUK_ASSERT(env->regbase_byteoff == 0);
80381 		}
80382 	}
80383 
80384 	return (duk_hobject *) env;
80385 }
80386 
80387 DUK_INTERNAL
80388 void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
80389                                                         duk_activation *act) {
80390 	duk_hobject *func;
80391 	duk_hobject *env;
80392 
80393 	DUK_ASSERT(thr != NULL);
80394 	func = DUK_ACT_GET_FUNC(act);
80395 	DUK_ASSERT(func != NULL);
80396 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
80397 
80398 	/*
80399 	 *  Delayed initialization only occurs for 'NEWENV' functions.
80400 	 */
80401 
80402 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80403 	DUK_ASSERT(act->lex_env == NULL);
80404 	DUK_ASSERT(act->var_env == NULL);
80405 
80406 	env = duk_create_activation_environment_record(thr, func, act->bottom_byteoff);
80407 	DUK_ASSERT(env != NULL);
80408 	/* 'act' is a stable pointer, so still OK. */
80409 
80410 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
80411 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
80412 	{
80413 		duk_hobject *p = env;
80414 		while (p) {
80415 			DUK_DDD(DUK_DDDPRINT("  -> %!ipO", (duk_heaphdr *) p));
80416 			p = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, p);
80417 		}
80418 	}
80419 #endif
80420 
80421 	act->lex_env = env;
80422 	act->var_env = env;
80423 	DUK_HOBJECT_INCREF(thr, env);  /* XXX: incref by count (here 2 times) */
80424 	DUK_HOBJECT_INCREF(thr, env);
80425 
80426 	duk_pop_unsafe(thr);
80427 }
80428 
80429 /*
80430  *  Closing environment records.
80431  *
80432  *  The environment record MUST be closed with the thread where its activation
80433  *  is; i.e. if 'env' is open, 'thr' must match env->thread, and the regbase
80434  *  and varmap must still be valid.  On entry, 'env' must be reachable.
80435  */
80436 
80437 DUK_INTERNAL void duk_js_close_environment_record(duk_hthread *thr, duk_hobject *env) {
80438 	duk_uint_fast32_t i;
80439 	duk_hobject *varmap;
80440 	duk_hstring *key;
80441 	duk_tval *tv;
80442 	duk_uint_t regnum;
80443 
80444 	DUK_ASSERT(thr != NULL);
80445 	DUK_ASSERT(env != NULL);
80446 
80447 	if (DUK_UNLIKELY(!DUK_HOBJECT_IS_DECENV(env))) {
80448 		DUK_DDD(DUK_DDDPRINT("env not a declarative record: %!iO", (duk_heaphdr *) env));
80449 		return;
80450 	}
80451 
80452 	varmap = ((duk_hdecenv *) env)->varmap;
80453 	if (varmap == NULL) {
80454 		DUK_DDD(DUK_DDDPRINT("env already closed: %!iO", (duk_heaphdr *) env));
80455 
80456 		return;
80457 	}
80458 	DUK_ASSERT(((duk_hdecenv *) env)->thread != NULL);
80459 	DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
80460 
80461 	DUK_DDD(DUK_DDDPRINT("closing env: %!iO", (duk_heaphdr *) env));
80462 	DUK_DDD(DUK_DDDPRINT("varmap: %!O", (duk_heaphdr *) varmap));
80463 
80464 	/* Env must be closed in the same thread as where it runs. */
80465 	DUK_ASSERT(((duk_hdecenv *) env)->thread == thr);
80466 
80467 	/* XXX: additional conditions when to close variables? we don't want to do it
80468 	 * unless the environment may have "escaped" (referenced in a function closure).
80469 	 * With delayed environments, the existence is probably good enough of a check.
80470 	 */
80471 
80472 	/* Note: we rely on the _Varmap having a bunch of nice properties, like:
80473 	 *  - being compacted and unmodified during this process
80474 	 *  - not containing an array part
80475 	 *  - having correct value types
80476 	 */
80477 
80478 	DUK_DDD(DUK_DDDPRINT("copying bound register values, %ld bound regs", (long) DUK_HOBJECT_GET_ENEXT(varmap)));
80479 
80480 	/* Copy over current variable values from value stack to the
80481 	 * environment record.  The scope object is empty but may
80482 	 * inherit from another scope which has conflicting names.
80483 	 */
80484 
80485 	/* XXX: Do this using a once allocated entry area, no side effects.
80486 	 * Hash part would need special treatment however (maybe copy, and
80487 	 * then realloc with hash part if large enough).
80488 	 */
80489 	for (i = 0; i < (duk_uint_fast32_t) DUK_HOBJECT_GET_ENEXT(varmap); i++) {
80490 		duk_size_t regbase_byteoff;
80491 
80492 		key = DUK_HOBJECT_E_GET_KEY(thr->heap, varmap, i);
80493 		DUK_ASSERT(key != NULL);   /* assume keys are compact in _Varmap */
80494 		DUK_ASSERT(!DUK_HOBJECT_E_SLOT_IS_ACCESSOR(thr->heap, varmap, i));  /* assume plain values */
80495 
80496 		tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, varmap, i);
80497 		DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80498 		DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
80499 #if defined(DUK_USE_FASTINT)
80500 		DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
80501 		regnum = (duk_uint_t) DUK_TVAL_GET_FASTINT_U32(tv);
80502 #else
80503 		regnum = (duk_uint_t) DUK_TVAL_GET_NUMBER(tv);
80504 #endif
80505 
80506 		regbase_byteoff = ((duk_hdecenv *) env)->regbase_byteoff;
80507 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum >= (duk_uint8_t *) thr->valstack);
80508 		DUK_ASSERT((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum < (duk_uint8_t *) thr->valstack_top);
80509 
80510 		/* If property already exists, overwrites silently.
80511 		 * Property is writable, but not deletable (not configurable
80512 		 * in terms of property attributes).
80513 		 */
80514 		duk_push_tval(thr, (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + regbase_byteoff + sizeof(duk_tval) * regnum));
80515 		DUK_DDD(DUK_DDDPRINT("closing identifier %!O -> reg %ld, value %!T",
80516 		                     (duk_heaphdr *) key,
80517 		                     (long) regnum,
80518 		                     (duk_tval *) duk_get_tval(thr, -1)));
80519 		duk_hobject_define_property_internal(thr, env, key, DUK_PROPDESC_FLAGS_WE);
80520 	}
80521 
80522 	/* NULL atomically to avoid inconsistent state + side effects. */
80523 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->thread);
80524 	DUK_HOBJECT_DECREF_NORZ(thr, ((duk_hdecenv *) env)->varmap);
80525 	((duk_hdecenv *) env)->thread = NULL;
80526 	((duk_hdecenv *) env)->varmap = NULL;
80527 
80528 	DUK_DDD(DUK_DDDPRINT("env after closing: %!O", (duk_heaphdr *) env));
80529 }
80530 
80531 /*
80532  *  GETIDREF: a GetIdentifierReference-like helper.
80533  *
80534  *  Provides a parent traversing lookup and a single level lookup
80535  *  (for HasBinding).
80536  *
80537  *  Instead of returning the value, returns a bunch of values allowing
80538  *  the caller to read, write, or delete the binding.  Value pointers
80539  *  are duk_tval pointers which can be mutated directly as long as
80540  *  refcounts are properly updated.  Note that any operation which may
80541  *  reallocate valstacks or compact objects may invalidate the returned
80542  *  duk_tval (but not object) pointers, so caller must be very careful.
80543  *
80544  *  If starting environment record 'env' is given, 'act' is ignored.
80545  *  However, if 'env' is NULL, the caller may identify, in 'act', an
80546  *  activation which hasn't had its declarative environment initialized
80547  *  yet.  The activation registers are then looked up, and its parent
80548  *  traversed normally.
80549  *
80550  *  The 'out' structure values are only valid if the function returns
80551  *  success (non-zero).
80552  */
80553 
80554 /* lookup name from an open declarative record's registers */
80555 DUK_LOCAL
80556 duk_bool_t duk__getid_open_decl_env_regs(duk_hthread *thr,
80557                                          duk_hstring *name,
80558                                          duk_hdecenv *env,
80559                                          duk__id_lookup_result *out) {
80560 	duk_tval *tv;
80561 	duk_size_t reg_rel;
80562 
80563 	DUK_ASSERT(thr != NULL);
80564 	DUK_ASSERT(name != NULL);
80565 	DUK_ASSERT(env != NULL);
80566 	DUK_ASSERT(out != NULL);
80567 
80568 	DUK_ASSERT(DUK_HOBJECT_IS_DECENV((duk_hobject *) env));
80569 	DUK_ASSERT_HDECENV_VALID(env);
80570 
80571 	if (env->thread == NULL) {
80572 		/* already closed */
80573 		return 0;
80574 	}
80575 	DUK_ASSERT(env->varmap != NULL);
80576 
80577 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, env->varmap, name);
80578 	if (DUK_UNLIKELY(tv == NULL)) {
80579 		return 0;
80580 	}
80581 
80582 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80583 	DUK_ASSERT(DUK_TVAL_GET_NUMBER(tv) <= (duk_double_t) DUK_UINT32_MAX);  /* limits */
80584 #if defined(DUK_USE_FASTINT)
80585 	DUK_ASSERT(DUK_TVAL_IS_FASTINT(tv));
80586 	reg_rel = (duk_size_t) DUK_TVAL_GET_FASTINT_U32(tv);
80587 #else
80588 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
80589 #endif
80590 	DUK_ASSERT_DISABLE(reg_rel >= 0);  /* unsigned */
80591 
80592 	tv = (duk_tval *) (void *) ((duk_uint8_t *) env->thread->valstack + env->regbase_byteoff + sizeof(duk_tval) * reg_rel);
80593 	DUK_ASSERT(tv >= env->thread->valstack && tv < env->thread->valstack_end);  /* XXX: more accurate? */
80594 
80595 	out->value = tv;
80596 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
80597 	out->env = (duk_hobject *) env;
80598 	out->holder = NULL;
80599 	out->has_this = 0;
80600 	return 1;
80601 }
80602 
80603 /* lookup name from current activation record's functions' registers */
80604 DUK_LOCAL
80605 duk_bool_t duk__getid_activation_regs(duk_hthread *thr,
80606                                       duk_hstring *name,
80607                                       duk_activation *act,
80608                                       duk__id_lookup_result *out) {
80609 	duk_tval *tv;
80610 	duk_hobject *func;
80611 	duk_hobject *varmap;
80612 	duk_size_t reg_rel;
80613 
80614 	DUK_ASSERT(thr != NULL);
80615 	DUK_ASSERT(name != NULL);
80616 	DUK_ASSERT(act != NULL);
80617 	DUK_ASSERT(out != NULL);
80618 
80619 	func = DUK_ACT_GET_FUNC(act);
80620 	DUK_ASSERT(func != NULL);
80621 	DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80622 
80623 	if (!DUK_HOBJECT_IS_COMPFUNC(func)) {
80624 		return 0;
80625 	}
80626 
80627 	/* XXX: move varmap to duk_hcompfunc struct field. */
80628 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, func, DUK_HTHREAD_STRING_INT_VARMAP(thr));
80629 	if (!tv) {
80630 		return 0;
80631 	}
80632 	DUK_ASSERT(DUK_TVAL_IS_OBJECT(tv));
80633 	varmap = DUK_TVAL_GET_OBJECT(tv);
80634 	DUK_ASSERT(varmap != NULL);
80635 
80636 	tv = duk_hobject_find_existing_entry_tval_ptr(thr->heap, varmap, name);
80637 	if (!tv) {
80638 		return 0;
80639 	}
80640 	DUK_ASSERT(DUK_TVAL_IS_NUMBER(tv));
80641 	reg_rel = (duk_size_t) DUK_TVAL_GET_NUMBER(tv);
80642 	DUK_ASSERT_DISABLE(reg_rel >= 0);
80643 	DUK_ASSERT(reg_rel < ((duk_hcompfunc *) func)->nregs);
80644 
80645 	tv = (duk_tval *) (void *) ((duk_uint8_t *) thr->valstack + act->bottom_byteoff);
80646 	tv += reg_rel;
80647 
80648 	out->value = tv;
80649 	out->attrs = DUK_PROPDESC_FLAGS_W;  /* registers are mutable, non-deletable */
80650 	out->env = NULL;
80651 	out->holder = NULL;
80652 	out->has_this = 0;
80653 	return 1;
80654 }
80655 
80656 DUK_LOCAL
80657 duk_bool_t duk__get_identifier_reference(duk_hthread *thr,
80658                                          duk_hobject *env,
80659                                          duk_hstring *name,
80660                                          duk_activation *act,
80661                                          duk_bool_t parents,
80662                                          duk__id_lookup_result *out) {
80663 	duk_tval *tv;
80664 	duk_uint_t sanity;
80665 
80666 	DUK_ASSERT(thr != NULL);
80667 	DUK_ASSERT(env != NULL || act != NULL);
80668 	DUK_ASSERT(name != NULL);
80669 	DUK_ASSERT(out != NULL);
80670 
80671 	DUK_ASSERT(!env || DUK_HOBJECT_IS_ENV(env));
80672 	DUK_ASSERT(!env || !DUK_HOBJECT_HAS_ARRAY_PART(env));
80673 
80674 	/*
80675 	 *  Conceptually, we look for the identifier binding by starting from
80676 	 *  'env' and following to chain of environment records (represented
80677 	 *  by the prototype chain).
80678 	 *
80679 	 *  If 'env' is NULL, the current activation does not yet have an
80680 	 *  allocated declarative environment record; this should be treated
80681 	 *  exactly as if the environment record existed but had no bindings
80682 	 *  other than register bindings.
80683 	 *
80684 	 *  Note: we assume that with the DUK_HOBJECT_FLAG_NEWENV cleared
80685 	 *  the environment will always be initialized immediately; hence
80686 	 *  a NULL 'env' should only happen with the flag set.  This is the
80687 	 *  case for: (1) function calls, and (2) strict, direct eval calls.
80688 	 */
80689 
80690 	if (env == NULL && act != NULL) {
80691 		duk_hobject *func;
80692 		duk_hcompfunc *f;
80693 
80694 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference: env is NULL, activation is non-NULL -> "
80695 		                     "delayed env case, look up activation regs first"));
80696 
80697 		/*
80698 		 *  Try registers
80699 		 */
80700 
80701 		if (duk__getid_activation_regs(thr, name, act, out)) {
80702 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80703 			                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80704 			                     "(found from register bindings when env=NULL)",
80705 			                     (duk_heaphdr *) name, (duk_tval *) out->value,
80706 			                     (long) out->attrs, (long) out->has_this,
80707 			                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80708 			return 1;
80709 		}
80710 
80711 		DUK_DDD(DUK_DDDPRINT("not found in current activation regs"));
80712 
80713 		/*
80714 		 *  Not found in registers, proceed to the parent record.
80715 		 *  Here we need to determine what the parent would be,
80716 		 *  if 'env' was not NULL (i.e. same logic as when initializing
80717 		 *  the record).
80718 		 *
80719 		 *  Note that environment initialization is only deferred when
80720 		 *  DUK_HOBJECT_HAS_NEWENV is set, and this only happens for:
80721 		 *    - Function code
80722 		 *    - Strict eval code
80723 		 *
80724 		 *  We only need to check _Lexenv here; _Varenv exists only if it
80725 		 *  differs from _Lexenv (and thus _Lexenv will also be present).
80726 		 */
80727 
80728 		if (!parents) {
80729 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
80730 			                     "(not found from register bindings when env=NULL)"));
80731 			goto fail_not_found;
80732 		}
80733 
80734 		func = DUK_ACT_GET_FUNC(act);
80735 		DUK_ASSERT(func != NULL);
80736 		DUK_ASSERT(DUK_HOBJECT_HAS_NEWENV(func));
80737 		f = (duk_hcompfunc *) func;
80738 
80739 		env = DUK_HCOMPFUNC_GET_LEXENV(thr->heap, f);
80740 		if (!env) {
80741 			env = thr->builtins[DUK_BIDX_GLOBAL_ENV];
80742 		}
80743 
80744 		DUK_DDD(DUK_DDDPRINT("continue lookup from env: %!iO",
80745 		                     (duk_heaphdr *) env));
80746 	}
80747 
80748 	/*
80749 	 *  Prototype walking starting from 'env'.
80750 	 *
80751 	 *  ('act' is not needed anywhere here.)
80752 	 */
80753 
80754 	sanity = DUK_HOBJECT_PROTOTYPE_CHAIN_SANITY;
80755 	while (env != NULL) {
80756 		duk_small_uint_t cl;
80757 		duk_uint_t attrs;
80758 
80759 		DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference, name=%!O, considering env=%p -> %!iO",
80760 		                     (duk_heaphdr *) name,
80761 		                     (void *) env,
80762 		                     (duk_heaphdr *) env));
80763 
80764 		DUK_ASSERT(env != NULL);
80765 		DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
80766 		DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
80767 
80768 		cl = DUK_HOBJECT_GET_CLASS_NUMBER(env);
80769 		DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV || cl == DUK_HOBJECT_CLASS_DECENV);
80770 		if (cl == DUK_HOBJECT_CLASS_DECENV) {
80771 			/*
80772 			 *  Declarative environment record.
80773 			 *
80774 			 *  Identifiers can never be stored in ancestors and are
80775 			 *  always plain values, so we can use an internal helper
80776 			 *  and access the value directly with an duk_tval ptr.
80777 			 *
80778 			 *  A closed environment is only indicated by it missing
80779 			 *  the "book-keeping" properties required for accessing
80780 			 *  register-bound variables.
80781 			 */
80782 
80783 			DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
80784 			if (duk__getid_open_decl_env_regs(thr, name, (duk_hdecenv *) env, out)) {
80785 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80786 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80787 				                     "(declarative environment record, scope open, found in regs)",
80788 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80789 				                     (long) out->attrs, (long) out->has_this,
80790 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80791 				return 1;
80792 			}
80793 
80794 			tv = duk_hobject_find_existing_entry_tval_ptr_and_attrs(thr->heap, env, name, &attrs);
80795 			if (tv) {
80796 				out->value = tv;
80797 				out->attrs = attrs;
80798 				out->env = env;
80799 				out->holder = env;
80800 				out->has_this = 0;
80801 
80802 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80803 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80804 				                     "(declarative environment record, found in properties)",
80805 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80806 				                     (long) out->attrs, (long) out->has_this,
80807 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80808 				return 1;
80809 			}
80810 		} else {
80811 			/*
80812 			 *  Object environment record.
80813 			 *
80814 			 *  Binding (target) object is an external, uncontrolled object.
80815 			 *  Identifier may be bound in an ancestor property, and may be
80816 			 *  an accessor.  Target can also be a Proxy which we must support
80817 			 *  here.
80818 			 */
80819 
80820 			/* XXX: we could save space by using _Target OR _This.  If _Target, assume
80821 			 * this binding is undefined.  If _This, assumes this binding is _This, and
80822 			 * target is also _This.  One property would then be enough.
80823 			 */
80824 
80825 			duk_hobject *target;
80826 			duk_bool_t found;
80827 
80828 			DUK_ASSERT(cl == DUK_HOBJECT_CLASS_OBJENV);
80829 			DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
80830 
80831 			target = ((duk_hobjenv *) env)->target;
80832 			DUK_ASSERT(target != NULL);
80833 
80834 			/* Target may be a Proxy or property may be an accessor, so we must
80835 			 * use an actual, Proxy-aware hasprop check here.
80836 			 *
80837 			 * out->holder is NOT set to the actual duk_hobject where the
80838 			 * property is found, but rather the object binding target object.
80839 			 */
80840 
80841 #if defined(DUK_USE_ES6_PROXY)
80842 			if (DUK_UNLIKELY(DUK_HOBJECT_IS_PROXY(target))) {
80843 				duk_tval tv_name;
80844 				duk_tval tv_target_tmp;
80845 
80846 				DUK_ASSERT(name != NULL);
80847 				DUK_TVAL_SET_STRING(&tv_name, name);
80848 				DUK_TVAL_SET_OBJECT(&tv_target_tmp, target);
80849 
80850 				found = duk_hobject_hasprop(thr, &tv_target_tmp, &tv_name);
80851 			} else
80852 #endif  /* DUK_USE_ES6_PROXY */
80853 			{
80854 				/* XXX: duk_hobject_hasprop() would be correct for
80855 				 * non-Proxy objects too, but it is about ~20-25%
80856 				 * slower at present so separate code paths for
80857 				 * Proxy and non-Proxy now.
80858 				 */
80859 				found = duk_hobject_hasprop_raw(thr, target, name);
80860 			}
80861 
80862 			if (found) {
80863 				out->value = NULL;  /* can't get value, may be accessor */
80864 				out->attrs = 0;     /* irrelevant when out->value == NULL */
80865 				out->env = env;
80866 				out->holder = target;
80867 				out->has_this = ((duk_hobjenv *) env)->has_this;
80868 
80869 				DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference successful: "
80870 				                     "name=%!O -> value=%!T, attrs=%ld, has_this=%ld, env=%!O, holder=%!O "
80871 				                     "(object environment record)",
80872 				                     (duk_heaphdr *) name, (duk_tval *) out->value,
80873 				                     (long) out->attrs, (long) out->has_this,
80874 				                     (duk_heaphdr *) out->env, (duk_heaphdr *) out->holder));
80875 				return 1;
80876 			}
80877 		}
80878 
80879 		if (!parents) {
80880 			DUK_DDD(DUK_DDDPRINT("duk__get_identifier_reference failed, no parent traversal "
80881 			                     "(not found from first traversed env)"));
80882 			goto fail_not_found;
80883 		}
80884 
80885                 if (DUK_UNLIKELY(sanity-- == 0)) {
80886                         DUK_ERROR_RANGE(thr, DUK_STR_PROTOTYPE_CHAIN_LIMIT);
80887 			DUK_WO_NORETURN(return 0;);
80888                 }
80889 		env = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, env);
80890 	}
80891 
80892 	/*
80893 	 *  Not found (even in global object)
80894 	 */
80895 
80896  fail_not_found:
80897 	return 0;
80898 }
80899 
80900 /*
80901  *  HASVAR: check identifier binding from a given environment record
80902  *  without traversing its parents.
80903  *
80904  *  This primitive is not exposed to user code as such, but is used
80905  *  internally for e.g. declaration binding instantiation.
80906  *
80907  *  See E5 Sections:
80908  *    10.2.1.1.1 HasBinding(N)
80909  *    10.2.1.2.1 HasBinding(N)
80910  *
80911  *  Note: strictness has no bearing on this check.  Hence we don't take
80912  *  a 'strict' parameter.
80913  */
80914 
80915 #if 0  /*unused*/
80916 DUK_INTERNAL
80917 duk_bool_t duk_js_hasvar_envrec(duk_hthread *thr,
80918                                 duk_hobject *env,
80919                                 duk_hstring *name) {
80920 	duk__id_lookup_result ref;
80921 	duk_bool_t parents;
80922 
80923 	DUK_DDD(DUK_DDDPRINT("hasvar: thr=%p, env=%p, name=%!O "
80924 	                     "(env -> %!dO)",
80925 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
80926 	                     (duk_heaphdr *) env));
80927 
80928 	DUK_ASSERT(thr != NULL);
80929 	DUK_ASSERT(env != NULL);
80930 	DUK_ASSERT(name != NULL);
80931 
80932         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
80933         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
80934 
80935 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
80936 	DUK_ASSERT(!DUK_HOBJECT_HAS_ARRAY_PART(env));
80937 
80938 	/* lookup results is ignored */
80939 	parents = 0;
80940 	return duk__get_identifier_reference(thr, env, name, NULL, parents, &ref);
80941 }
80942 #endif
80943 
80944 /*
80945  *  GETVAR
80946  *
80947  *  See E5 Sections:
80948  *    11.1.2 Identifier Reference
80949  *    10.3.1 Identifier Resolution
80950  *    11.13.1 Simple Assignment  [example of where the Reference is GetValue'd]
80951  *    8.7.1 GetValue (V)
80952  *    8.12.1 [[GetOwnProperty]] (P)
80953  *    8.12.2 [[GetProperty]] (P)
80954  *    8.12.3 [[Get]] (P)
80955  *
80956  *  If 'throw' is true, always leaves two values on top of stack: [val this].
80957  *
80958  *  If 'throw' is false, returns 0 if identifier cannot be resolved, and the
80959  *  stack will be unaffected in this case.  If identifier is resolved, returns
80960  *  1 and leaves [val this] on top of stack.
80961  *
80962  *  Note: the 'strict' flag of a reference returned by GetIdentifierReference
80963  *  is ignored by GetValue.  Hence we don't take a 'strict' parameter.
80964  *
80965  *  The 'throw' flag is needed for implementing 'typeof' for an unreferenced
80966  *  identifier.  An unreference identifier in other contexts generates a
80967  *  ReferenceError.
80968  */
80969 
80970 DUK_LOCAL
80971 duk_bool_t duk__getvar_helper(duk_hthread *thr,
80972                               duk_hobject *env,
80973                               duk_activation *act,
80974                               duk_hstring *name,
80975                               duk_bool_t throw_flag) {
80976 	duk__id_lookup_result ref;
80977 	duk_tval tv_tmp_obj;
80978 	duk_tval tv_tmp_key;
80979 	duk_bool_t parents;
80980 
80981 	DUK_DDD(DUK_DDDPRINT("getvar: thr=%p, env=%p, act=%p, name=%!O "
80982 	                     "(env -> %!dO)",
80983 	                     (void *) thr, (void *) env, (void *) act,
80984 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
80985 
80986 	DUK_ASSERT(thr != NULL);
80987 	DUK_ASSERT(name != NULL);
80988 	/* env and act may be NULL */
80989 
80990 	DUK_STATS_INC(thr->heap, stats_getvar_all);
80991 
80992         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
80993         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
80994 
80995 	parents = 1;     /* follow parent chain */
80996 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
80997 		if (ref.value) {
80998 			duk_push_tval(thr, ref.value);
80999 			duk_push_undefined(thr);
81000 		} else {
81001 			DUK_ASSERT(ref.holder != NULL);
81002 
81003 			/* ref.holder is safe across the getprop call (even
81004 			 * with side effects) because 'env' is reachable and
81005 			 * ref.holder is a direct heap pointer.
81006 			 */
81007 
81008 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81009 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81010 			(void) duk_hobject_getprop(thr, &tv_tmp_obj, &tv_tmp_key);  /* [value] */
81011 
81012 			if (ref.has_this) {
81013 				duk_push_hobject(thr, ref.holder);
81014 			} else {
81015 				duk_push_undefined(thr);
81016 			}
81017 
81018 			/* [value this] */
81019 		}
81020 
81021 		return 1;
81022 	} else {
81023 		if (throw_flag) {
81024 			DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81025 			               "identifier '%s' undefined",
81026 			               (const char *) DUK_HSTRING_GET_DATA(name));
81027 			DUK_WO_NORETURN(return 0;);
81028 		}
81029 
81030 		return 0;
81031 	}
81032 }
81033 
81034 DUK_INTERNAL
81035 duk_bool_t duk_js_getvar_envrec(duk_hthread *thr,
81036                                 duk_hobject *env,
81037                                 duk_hstring *name,
81038                                 duk_bool_t throw_flag) {
81039 	return duk__getvar_helper(thr, env, NULL, name, throw_flag);
81040 }
81041 
81042 DUK_INTERNAL
81043 duk_bool_t duk_js_getvar_activation(duk_hthread *thr,
81044                                     duk_activation *act,
81045                                     duk_hstring *name,
81046                                     duk_bool_t throw_flag) {
81047 	DUK_ASSERT(act != NULL);
81048 	return duk__getvar_helper(thr, act->lex_env, act, name, throw_flag);
81049 }
81050 
81051 /*
81052  *  PUTVAR
81053  *
81054  *  See E5 Sections:
81055  *    11.1.2 Identifier Reference
81056  *    10.3.1 Identifier Resolution
81057  *    11.13.1 Simple Assignment  [example of where the Reference is PutValue'd]
81058  *    8.7.2 PutValue (V,W)  [see especially step 3.b, undefined -> automatic global in non-strict mode]
81059  *    8.12.4 [[CanPut]] (P)
81060  *    8.12.5 [[Put]] (P)
81061  *
81062  *  Note: may invalidate any valstack (or object) duk_tval pointers because
81063  *  putting a value may reallocate any object or any valstack.  Caller beware.
81064  */
81065 
81066 DUK_LOCAL
81067 void duk__putvar_helper(duk_hthread *thr,
81068                         duk_hobject *env,
81069                         duk_activation *act,
81070                         duk_hstring *name,
81071                         duk_tval *val,
81072                         duk_bool_t strict) {
81073 	duk__id_lookup_result ref;
81074 	duk_tval tv_tmp_obj;
81075 	duk_tval tv_tmp_key;
81076 	duk_bool_t parents;
81077 
81078 	DUK_STATS_INC(thr->heap, stats_putvar_all);
81079 
81080 	DUK_DDD(DUK_DDDPRINT("putvar: thr=%p, env=%p, act=%p, name=%!O, val=%p, strict=%ld "
81081 	                     "(env -> %!dO, val -> %!T)",
81082 	                     (void *) thr, (void *) env, (void *) act,
81083 	                     (duk_heaphdr *) name, (void *) val, (long) strict,
81084 	                     (duk_heaphdr *) env, (duk_tval *) val));
81085 
81086 	DUK_ASSERT(thr != NULL);
81087 	DUK_ASSERT(name != NULL);
81088 	DUK_ASSERT(val != NULL);
81089 	/* env and act may be NULL */
81090 
81091         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(env);
81092         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81093 	DUK_ASSERT_REFCOUNT_NONZERO_TVAL(val);
81094 
81095 	/*
81096 	 *  In strict mode E5 protects 'eval' and 'arguments' from being
81097 	 *  assigned to (or even declared anywhere).  Attempt to do so
81098 	 *  should result in a compile time SyntaxError.  See the internal
81099 	 *  design documentation for details.
81100 	 *
81101 	 *  Thus, we should never come here, run-time, for strict code,
81102 	 *  and name 'eval' or 'arguments'.
81103 	 */
81104 
81105 	DUK_ASSERT(!strict ||
81106 	           (name != DUK_HTHREAD_STRING_EVAL(thr) &&
81107 	            name != DUK_HTHREAD_STRING_LC_ARGUMENTS(thr)));
81108 
81109 	/*
81110 	 *  Lookup variable and update in-place if found.
81111 	 */
81112 
81113 	parents = 1;     /* follow parent chain */
81114 
81115 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81116 		if (ref.value && (ref.attrs & DUK_PROPDESC_FLAG_WRITABLE)) {
81117 			/* Update duk_tval in-place if pointer provided and the
81118 			 * property is writable.  If the property is not writable
81119 			 * (immutable binding), use duk_hobject_putprop() which
81120 			 * will respect mutability.
81121 			 */
81122 			duk_tval *tv_val;
81123 
81124 			tv_val = ref.value;
81125 			DUK_ASSERT(tv_val != NULL);
81126 			DUK_TVAL_SET_TVAL_UPDREF(thr, tv_val, val);  /* side effects */
81127 
81128 			/* ref.value invalidated here */
81129 		} else {
81130 			DUK_ASSERT(ref.holder != NULL);
81131 
81132 			DUK_TVAL_SET_OBJECT(&tv_tmp_obj, ref.holder);
81133 			DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81134 			(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, strict);
81135 
81136 			/* ref.value invalidated here */
81137 		}
81138 
81139 		return;
81140 	}
81141 
81142 	/*
81143 	 *  Not found: write to global object (non-strict) or ReferenceError
81144 	 *  (strict); see E5 Section 8.7.2, step 3.
81145 	 */
81146 
81147 	if (strict) {
81148 		DUK_DDD(DUK_DDDPRINT("identifier binding not found, strict => reference error"));
81149 		DUK_ERROR_FMT1(thr, DUK_ERR_REFERENCE_ERROR,
81150 		               "identifier '%s' undefined",
81151 		               (const char *) DUK_HSTRING_GET_DATA(name));
81152 		DUK_WO_NORETURN(return;);
81153 	}
81154 
81155 	DUK_DDD(DUK_DDDPRINT("identifier binding not found, not strict => set to global"));
81156 
81157 	DUK_TVAL_SET_OBJECT(&tv_tmp_obj, thr->builtins[DUK_BIDX_GLOBAL]);
81158 	DUK_TVAL_SET_STRING(&tv_tmp_key, name);
81159 	(void) duk_hobject_putprop(thr, &tv_tmp_obj, &tv_tmp_key, val, 0);  /* 0 = no throw */
81160 
81161 	/* NB: 'val' may be invalidated here because put_value may realloc valstack,
81162 	 * caller beware.
81163 	 */
81164 }
81165 
81166 DUK_INTERNAL
81167 void duk_js_putvar_envrec(duk_hthread *thr,
81168                           duk_hobject *env,
81169                           duk_hstring *name,
81170                           duk_tval *val,
81171                           duk_bool_t strict) {
81172 	duk__putvar_helper(thr, env, NULL, name, val, strict);
81173 }
81174 
81175 DUK_INTERNAL
81176 void duk_js_putvar_activation(duk_hthread *thr,
81177                               duk_activation *act,
81178                               duk_hstring *name,
81179                               duk_tval *val,
81180                               duk_bool_t strict) {
81181 	DUK_ASSERT(act != NULL);
81182 	duk__putvar_helper(thr, act->lex_env, act, name, val, strict);
81183 }
81184 
81185 /*
81186  *  DELVAR
81187  *
81188  *  See E5 Sections:
81189  *    11.4.1 The delete operator
81190  *    10.2.1.1.5 DeleteBinding (N)  [declarative environment record]
81191  *    10.2.1.2.5 DeleteBinding (N)  [object environment record]
81192  *
81193  *  Variable bindings established inside eval() are deletable (configurable),
81194  *  other bindings are not, including variables declared in global level.
81195  *  Registers are always non-deletable, and the deletion of other bindings
81196  *  is controlled by the configurable flag.
81197  *
81198  *  For strict mode code, the 'delete' operator should fail with a compile
81199  *  time SyntaxError if applied to identifiers.  Hence, no strict mode
81200  *  run-time deletion of identifiers should ever happen.  This function
81201  *  should never be called from strict mode code!
81202  */
81203 
81204 DUK_LOCAL
81205 duk_bool_t duk__delvar_helper(duk_hthread *thr,
81206                               duk_hobject *env,
81207                               duk_activation *act,
81208                               duk_hstring *name) {
81209 	duk__id_lookup_result ref;
81210 	duk_bool_t parents;
81211 
81212 	DUK_DDD(DUK_DDDPRINT("delvar: thr=%p, env=%p, act=%p, name=%!O "
81213 	                     "(env -> %!dO)",
81214 	                     (void *) thr, (void *) env, (void *) act,
81215 	                     (duk_heaphdr *) name, (duk_heaphdr *) env));
81216 
81217 	DUK_ASSERT(thr != NULL);
81218 	DUK_ASSERT(name != NULL);
81219 	/* env and act may be NULL */
81220 
81221         DUK_ASSERT_REFCOUNT_NONZERO_HEAPHDR(name);
81222 
81223 	parents = 1;     /* follow parent chain */
81224 
81225 	if (duk__get_identifier_reference(thr, env, name, act, parents, &ref)) {
81226 		if (ref.value && !(ref.attrs & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
81227 			/* Identifier found in registers (always non-deletable)
81228 			 * or declarative environment record and non-configurable.
81229 			 */
81230 			return 0;
81231 		}
81232 		DUK_ASSERT(ref.holder != NULL);
81233 
81234 		return duk_hobject_delprop_raw(thr, ref.holder, name, 0);
81235 	}
81236 
81237 	/*
81238 	 *  Not found (even in global object).
81239 	 *
81240 	 *  In non-strict mode this is a silent SUCCESS (!), see E5 Section 11.4.1,
81241 	 *  step 3.b.  In strict mode this case is a compile time SyntaxError so
81242 	 *  we should not come here.
81243 	 */
81244 
81245 	DUK_DDD(DUK_DDDPRINT("identifier to be deleted not found: name=%!O "
81246 	                     "(treated as silent success)",
81247 	                     (duk_heaphdr *) name));
81248 	return 1;
81249 }
81250 
81251 #if 0  /*unused*/
81252 DUK_INTERNAL
81253 duk_bool_t duk_js_delvar_envrec(duk_hthread *thr,
81254                                 duk_hobject *env,
81255                                 duk_hstring *name) {
81256 	return duk__delvar_helper(thr, env, NULL, name);
81257 }
81258 #endif
81259 
81260 DUK_INTERNAL
81261 duk_bool_t duk_js_delvar_activation(duk_hthread *thr,
81262                                     duk_activation *act,
81263                                     duk_hstring *name) {
81264 	DUK_ASSERT(act != NULL);
81265 	return duk__delvar_helper(thr, act->lex_env, act, name);
81266 }
81267 
81268 /*
81269  *  DECLVAR
81270  *
81271  *  See E5 Sections:
81272  *    10.4.3 Entering Function Code
81273  *    10.5 Declaration Binding Instantion
81274  *    12.2 Variable Statement
81275  *    11.1.2 Identifier Reference
81276  *    10.3.1 Identifier Resolution
81277  *
81278  *  Variable declaration behavior is mainly discussed in Section 10.5,
81279  *  and is not discussed in the execution semantics (Sections 11-13).
81280  *
81281  *  Conceptually declarations happen when code (global, eval, function)
81282  *  is entered, before any user code is executed.  In practice, register-
81283  *  bound identifiers are 'declared' automatically (by virtue of being
81284  *  allocated to registers with the initial value 'undefined').  Other
81285  *  identifiers are declared in the function prologue with this primitive.
81286  *
81287  *  Since non-register bindings eventually back to an internal object's
81288  *  properties, the 'prop_flags' argument is used to specify binding
81289  *  type:
81290  *
81291  *    - Immutable binding: set DUK_PROPDESC_FLAG_WRITABLE to false
81292  *    - Non-deletable binding: set DUK_PROPDESC_FLAG_CONFIGURABLE to false
81293  *    - The flag DUK_PROPDESC_FLAG_ENUMERABLE should be set, although it
81294  *      doesn't really matter for internal objects
81295  *
81296  *  All bindings are non-deletable mutable bindings except:
81297  *
81298  *    - Declarations in eval code (mutable, deletable)
81299  *    - 'arguments' binding in strict function code (immutable)
81300  *    - Function name binding of a function expression (immutable)
81301  *
81302  *  Declarations may go to declarative environment records (always
81303  *  so for functions), but may also go to object environment records
81304  *  (e.g. global code).  The global object environment has special
81305  *  behavior when re-declaring a function (but not a variable); see
81306  *  E5.1 specification, Section 10.5, step 5.e.
81307  *
81308  *  Declarations always go to the 'top-most' environment record, i.e.
81309  *  we never check the record chain.  It's not an error even if a
81310  *  property (even an immutable or non-deletable one) of the same name
81311  *  already exists.
81312  *
81313  *  If a declared variable already exists, its value needs to be updated
81314  *  (if possible).  Returns 1 if a PUTVAR needs to be done by the caller;
81315  *  otherwise returns 0.
81316  */
81317 
81318 DUK_LOCAL
81319 duk_bool_t duk__declvar_helper(duk_hthread *thr,
81320                                duk_hobject *env,
81321                                duk_hstring *name,
81322                                duk_tval *val,
81323                                duk_small_uint_t prop_flags,
81324                                duk_bool_t is_func_decl) {
81325 	duk_hobject *holder;
81326 	duk_bool_t parents;
81327 	duk__id_lookup_result ref;
81328 	duk_tval *tv;
81329 
81330 	DUK_DDD(DUK_DDDPRINT("declvar: thr=%p, env=%p, name=%!O, val=%!T, prop_flags=0x%08lx, is_func_decl=%ld "
81331 	                     "(env -> %!iO)",
81332 	                     (void *) thr, (void *) env, (duk_heaphdr *) name,
81333 	                     (duk_tval *) val, (unsigned long) prop_flags,
81334 	                     (unsigned int) is_func_decl, (duk_heaphdr *) env));
81335 
81336 	DUK_ASSERT(thr != NULL);
81337 	DUK_ASSERT(env != NULL);
81338 	DUK_ASSERT(name != NULL);
81339 	DUK_ASSERT(val != NULL);
81340 
81341 	/* Note: in strict mode the compiler should reject explicit
81342 	 * declaration of 'eval' or 'arguments'.  However, internal
81343 	 * bytecode may declare 'arguments' in the function prologue.
81344 	 * We don't bother checking (or asserting) for these now.
81345 	 */
81346 
81347 	/* Note: val is a stable duk_tval pointer.  The caller makes
81348 	 * a value copy into its stack frame, so 'tv_val' is not subject
81349 	 * to side effects here.
81350 	 */
81351 
81352 	/*
81353 	 *  Check whether already declared.
81354 	 *
81355 	 *  We need to check whether the binding exists in the environment
81356 	 *  without walking its parents.  However, we still need to check
81357 	 *  register-bound identifiers and the prototype chain of an object
81358 	 *  environment target object.
81359 	 */
81360 
81361 	parents = 0;  /* just check 'env' */
81362 	if (duk__get_identifier_reference(thr, env, name, NULL, parents, &ref)) {
81363 		duk_int_t e_idx;
81364 		duk_int_t h_idx;
81365 		duk_small_uint_t flags;
81366 
81367 		/*
81368 		 *  Variable already declared, ignore re-declaration.
81369 		 *  The only exception is the updated behavior of E5.1 for
81370 		 *  global function declarations, E5.1 Section 10.5, step 5.e.
81371 		 *  This behavior does not apply to global variable declarations.
81372 		 */
81373 
81374 		if (!(is_func_decl && env == thr->builtins[DUK_BIDX_GLOBAL_ENV])) {
81375 			DUK_DDD(DUK_DDDPRINT("re-declare a binding, ignoring"));
81376 			return 1;  /* 1 -> needs a PUTVAR */
81377 		}
81378 
81379 		/*
81380 		 *  Special behavior in E5.1.
81381 		 *
81382 		 *  Note that even though parents == 0, the conflicting property
81383 		 *  may be an inherited property (currently our global object's
81384 		 *  prototype is Object.prototype).  Step 5.e first operates on
81385 		 *  the existing property (which is potentially in an ancestor)
81386 		 *  and then defines a new property in the global object (and
81387 		 *  never modifies the ancestor).
81388 		 *
81389 		 *  Also note that this logic would become even more complicated
81390 		 *  if the conflicting property might be a virtual one.  Object
81391 		 *  prototype has no virtual properties, though.
81392 		 *
81393 		 *  XXX: this is now very awkward, rework.
81394 		 */
81395 
81396 		DUK_DDD(DUK_DDDPRINT("re-declare a function binding in global object, "
81397 		                     "updated E5.1 processing"));
81398 
81399 		DUK_ASSERT(ref.holder != NULL);
81400 		holder = ref.holder;
81401 
81402 		/* holder will be set to the target object, not the actual object
81403 		 * where the property was found (see duk__get_identifier_reference()).
81404 		 */
81405 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(holder) == DUK_HOBJECT_CLASS_GLOBAL);
81406 		DUK_ASSERT(!DUK_HOBJECT_HAS_EXOTIC_ARRAY(holder));  /* global object doesn't have array part */
81407 
81408 		/* XXX: use a helper for prototype traversal; no loop check here */
81409 		/* must be found: was found earlier, and cannot be inherited */
81410 		for (;;) {
81411 			DUK_ASSERT(holder != NULL);
81412 			if (duk_hobject_find_existing_entry(thr->heap, holder, name, &e_idx, &h_idx)) {
81413 				DUK_ASSERT(e_idx >= 0);
81414 				break;
81415 			}
81416 			/* SCANBUILD: NULL pointer dereference, doesn't actually trigger,
81417 			 * asserted above.
81418 			 */
81419 			holder = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, holder);
81420 		}
81421 		DUK_ASSERT(holder != NULL);
81422 		DUK_ASSERT(e_idx >= 0);
81423 		/* SCANBUILD: scan-build produces a NULL pointer dereference warning
81424 		 * below; it never actually triggers because holder is actually never
81425 		 * NULL.
81426 		 */
81427 
81428 		/* ref.holder is global object, holder is the object with the
81429 		 * conflicting property.
81430 		 */
81431 
81432 		flags = DUK_HOBJECT_E_GET_FLAGS(thr->heap, holder, e_idx);
81433 		if (!(flags & DUK_PROPDESC_FLAG_CONFIGURABLE)) {
81434 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
81435 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
81436 				                     "accessor -> reject"));
81437 				goto fail_existing_attributes;
81438 			}
81439 			if (!((flags & DUK_PROPDESC_FLAG_WRITABLE) &&
81440 			      (flags & DUK_PROPDESC_FLAG_ENUMERABLE))) {
81441 				DUK_DDD(DUK_DDDPRINT("existing property is a non-configurable "
81442 				                     "plain property which is not writable and "
81443 				                     "enumerable -> reject"));
81444 				goto fail_existing_attributes;
81445 			}
81446 
81447 			DUK_DDD(DUK_DDDPRINT("existing property is not configurable but "
81448 			                     "is plain, enumerable, and writable -> "
81449 			                     "allow redeclaration"));
81450 		}
81451 
81452 		if (holder == ref.holder) {
81453 			/* XXX: if duk_hobject_define_property_internal() was updated
81454 			 * to handle a pre-existing accessor property, this would be
81455 			 * a simple call (like for the ancestor case).
81456 			 */
81457 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in global object itself"));
81458 
81459 			if (flags & DUK_PROPDESC_FLAG_ACCESSOR) {
81460 				duk_hobject *tmp;
81461 
81462 				tmp = DUK_HOBJECT_E_GET_VALUE_GETTER(thr->heap, holder, e_idx);
81463 				DUK_HOBJECT_E_SET_VALUE_GETTER(thr->heap, holder, e_idx, NULL);
81464 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
81465 				DUK_UNREF(tmp);
81466 				tmp = DUK_HOBJECT_E_GET_VALUE_SETTER(thr->heap, holder, e_idx);
81467 				DUK_HOBJECT_E_SET_VALUE_SETTER(thr->heap, holder, e_idx, NULL);
81468 				DUK_HOBJECT_DECREF_ALLOWNULL(thr, tmp);
81469 				DUK_UNREF(tmp);
81470 			} else {
81471 				tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
81472 				DUK_TVAL_SET_UNDEFINED_UPDREF(thr, tv);
81473 			}
81474 
81475 			/* Here val would be potentially invalid if we didn't make
81476 			 * a value copy at the caller.
81477 			 */
81478 
81479 			tv = DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx);
81480 			DUK_TVAL_SET_TVAL(tv, val);
81481 			DUK_TVAL_INCREF(thr, tv);
81482 			DUK_HOBJECT_E_SET_FLAGS(thr->heap, holder, e_idx, prop_flags);
81483 
81484 			DUK_DDD(DUK_DDDPRINT("updated global binding, final result: "
81485 			                     "value -> %!T, prop_flags=0x%08lx",
81486 			                     (duk_tval *) DUK_HOBJECT_E_GET_VALUE_TVAL_PTR(thr->heap, holder, e_idx),
81487 			                     (unsigned long) prop_flags));
81488 		} else {
81489 			DUK_DDD(DUK_DDDPRINT("redefine, offending property in ancestor"));
81490 
81491 			DUK_ASSERT(ref.holder == thr->builtins[DUK_BIDX_GLOBAL]);
81492 			duk_push_tval(thr, val);
81493 			duk_hobject_define_property_internal(thr, ref.holder, name, prop_flags);
81494 		}
81495 
81496 		return 0;
81497 	}
81498 
81499 	/*
81500 	 *  Not found (in registers or record objects).  Declare
81501 	 *  to current variable environment.
81502 	 */
81503 
81504 	/*
81505 	 *  Get holder object
81506 	 */
81507 
81508 	if (DUK_HOBJECT_IS_DECENV(env)) {
81509 		DUK_ASSERT_HDECENV_VALID((duk_hdecenv *) env);
81510 		holder = env;
81511 	} else {
81512 		DUK_ASSERT_HOBJENV_VALID((duk_hobjenv *) env);
81513 		holder = ((duk_hobjenv *) env)->target;
81514 		DUK_ASSERT(holder != NULL);
81515 	}
81516 
81517 	/*
81518 	 *  Define new property
81519 	 *
81520 	 *  Note: this may fail if the holder is not extensible.
81521 	 */
81522 
81523 	/* XXX: this is awkward as we use an internal method which doesn't handle
81524 	 * extensibility etc correctly.  Basically we'd want to do a [[DefineOwnProperty]]
81525 	 * or Object.defineProperty() here.
81526 	 */
81527 
81528 	if (!DUK_HOBJECT_HAS_EXTENSIBLE(holder)) {
81529 		goto fail_not_extensible;
81530 	}
81531 
81532 	duk_push_hobject(thr, holder);
81533 	duk_push_hstring(thr, name);
81534 	duk_push_tval(thr, val);
81535 	duk_xdef_prop(thr, -3, prop_flags);  /* [holder name val] -> [holder] */
81536 	duk_pop_unsafe(thr);
81537 
81538 	return 0;
81539 
81540  fail_existing_attributes:
81541  fail_not_extensible:
81542 	DUK_ERROR_TYPE(thr, "declaration failed");
81543 	DUK_WO_NORETURN(return 0;);
81544 }
81545 
81546 DUK_INTERNAL
81547 duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
81548                                      duk_activation *act,
81549                                      duk_hstring *name,
81550                                      duk_tval *val,
81551                                      duk_small_uint_t prop_flags,
81552                                      duk_bool_t is_func_decl) {
81553 	duk_hobject *env;
81554 	duk_tval tv_val_copy;
81555 
81556 	DUK_ASSERT(act != NULL);
81557 
81558 	/*
81559 	 *  Make a value copy of the input val.  This ensures that
81560 	 *  side effects cannot invalidate the pointer.
81561 	 */
81562 
81563 	DUK_TVAL_SET_TVAL(&tv_val_copy, val);
81564 	val = &tv_val_copy;
81565 
81566 	/*
81567 	 *  Delayed env creation check
81568 	 */
81569 
81570 	if (!act->var_env) {
81571 		DUK_ASSERT(act->lex_env == NULL);
81572 		duk_js_init_activation_environment_records_delayed(thr, act);
81573 		/* 'act' is a stable pointer, so still OK. */
81574 	}
81575 	DUK_ASSERT(act->lex_env != NULL);
81576 	DUK_ASSERT(act->var_env != NULL);
81577 
81578 	env = act->var_env;
81579 	DUK_ASSERT(env != NULL);
81580 	DUK_ASSERT(DUK_HOBJECT_IS_ENV(env));
81581 
81582 	return duk__declvar_helper(thr, env, name, val, prop_flags, is_func_decl);
81583 }
81584 #line 1 "duk_lexer.c"
81585 /*
81586  *  Lexer for source files, ToNumber() string conversions, RegExp expressions,
81587  *  and JSON.
81588  *
81589  *  Provides a stream of ECMAScript tokens from an UTF-8/CESU-8 buffer.  The
81590  *  caller can also rewind the token stream into a certain position which is
81591  *  needed by the compiler part for multi-pass scanning.  Tokens are
81592  *  represented as duk_token structures, and contain line number information.
81593  *  Token types are identified with DUK_TOK_* defines.
81594  *
81595  *  Characters are decoded into a fixed size lookup window consisting of
81596  *  decoded Unicode code points, with window positions past the end of the
81597  *  input filled with an invalid codepoint (-1).  The tokenizer can thus
81598  *  perform multiple character lookups efficiently and with few sanity
81599  *  checks (such as access outside the end of the input), which keeps the
81600  *  tokenization code small at the cost of performance.
81601  *
81602  *  Character data in tokens, such as identifier names and string literals,
81603  *  is encoded into CESU-8 format on-the-fly while parsing the token in
81604  *  question.  The string data is made reachable to garbage collection by
81605  *  placing the token-related values in value stack entries allocated for
81606  *  this purpose by the caller.  The characters exist in Unicode code point
81607  *  form only in the fixed size lookup window, which keeps character data
81608  *  expansion (of especially ASCII data) low.
81609  *
81610  *  Token parsing supports the full range of Unicode characters as described
81611  *  in the E5 specification.  Parsing has been optimized for ASCII characters
81612  *  because ordinary ECMAScript code consists almost entirely of ASCII
81613  *  characters.  Matching of complex Unicode codepoint sets (such as in the
81614  *  IdentifierStart and IdentifierPart productions) is optimized for size,
81615  *  and is done using a linear scan of a bit-packed list of ranges.  This is
81616  *  very slow, but should never be entered unless the source code actually
81617  *  contains Unicode characters.
81618  *
81619  *  ECMAScript tokenization is partially context sensitive.  First,
81620  *  additional future reserved words are recognized in strict mode (see E5
81621  *  Section 7.6.1.2).  Second, a forward slash character ('/') can be
81622  *  recognized either as starting a RegExp literal or as a division operator,
81623  *  depending on context.  The caller must provide necessary context flags
81624  *  when requesting a new token.
81625  *
81626  *  Future work:
81627  *
81628  *    * Make line number tracking optional, as it consumes space.
81629  *
81630  *    * Add a feature flag for disabling UTF-8 decoding of input, as most
81631  *      source code is ASCII.  Because of Unicode escapes written in ASCII,
81632  *      this does not allow Unicode support to be removed from e.g.
81633  *      duk_unicode_is_identifier_start() nor does it allow removal of CESU-8
81634  *      encoding of e.g. string literals.
81635  *
81636  *    * Add a feature flag for disabling Unicode compliance of e.g. identifier
81637  *      names.  This allows for a build more than a kilobyte smaller, because
81638  *      Unicode ranges needed by duk_unicode_is_identifier_start() and
81639  *      duk_unicode_is_identifier_part() can be dropped.  String literals
81640  *      should still be allowed to contain escaped Unicode, so this still does
81641  *      not allow removal of CESU-8 encoding of e.g. string literals.
81642  *
81643  *    * Character lookup tables for codepoints above BMP could be stripped.
81644  *
81645  *    * Strictly speaking, E5 specification requires that source code consists
81646  *      of 16-bit code units, and if not, must be conceptually converted to
81647  *      that format first.  The current lexer processes Unicode code points
81648  *      and allows characters outside the BMP.  These should be converted to
81649  *      surrogate pairs while reading the source characters into the window,
81650  *      not after tokens have been formed (as is done now).  However, the fix
81651  *      is not trivial because two characters are decoded from one codepoint.
81652  *
81653  *    * Optimize for speed as well as size.  Large if-else ladders are (at
81654  *      least potentially) slow.
81655  */
81656 
81657 /* #include duk_internal.h -> already included */
81658 
81659 /*
81660  *  Various defines and file specific helper macros
81661  */
81662 
81663 #define DUK__MAX_RE_DECESC_DIGITS     9
81664 #define DUK__MAX_RE_QUANT_DIGITS      9   /* Does not allow e.g. 2**31-1, but one more would allow overflows of u32. */
81665 
81666 /* whether to use macros or helper function depends on call count */
81667 #define DUK__ISDIGIT(x)          ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_9)
81668 #define DUK__ISHEXDIGIT(x)       duk__is_hex_digit((x))
81669 #define DUK__ISOCTDIGIT(x)       ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_7)
81670 #define DUK__ISDIGIT03(x)        ((x) >= DUK_ASC_0 && (x) <= DUK_ASC_3)
81671 #define DUK__ISDIGIT47(x)        ((x) >= DUK_ASC_4 && (x) <= DUK_ASC_7)
81672 
81673 /* lexer character window helpers */
81674 #define DUK__LOOKUP(lex_ctx,idx)            ((lex_ctx)->window[(idx)].codepoint)
81675 #define DUK__ADVANCECHARS(lex_ctx,count)    duk__advance_chars((lex_ctx), (count))
81676 #define DUK__ADVANCEBYTES(lex_ctx,count)    duk__advance_bytes((lex_ctx), (count))
81677 #define DUK__INITBUFFER(lex_ctx)            duk__initbuffer((lex_ctx))
81678 #define DUK__APPENDBUFFER(lex_ctx,x)        duk__appendbuffer((lex_ctx), (duk_codepoint_t) (x))
81679 #define DUK__APPENDBUFFER_ASCII(lex_ctx,x)  duk__appendbuffer_ascii((lex_ctx), (duk_codepoint_t) (x))
81680 
81681 /* lookup shorthands (note: assume context variable is named 'lex_ctx') */
81682 #define DUK__L0()  DUK__LOOKUP(lex_ctx, 0)
81683 #define DUK__L1()  DUK__LOOKUP(lex_ctx, 1)
81684 #define DUK__L2()  DUK__LOOKUP(lex_ctx, 2)
81685 #define DUK__L3()  DUK__LOOKUP(lex_ctx, 3)
81686 #define DUK__L4()  DUK__LOOKUP(lex_ctx, 4)
81687 #define DUK__L5()  DUK__LOOKUP(lex_ctx, 5)
81688 
81689 /* packed advance/token number macro used by multiple functions */
81690 #define DUK__ADVTOK(advbytes,tok)  ((((advbytes) * sizeof(duk_lexer_codepoint)) << 8) + (tok))
81691 
81692 /*
81693  *  Advance lookup window by N characters, filling in new characters as
81694  *  necessary.  After returning caller is guaranteed a character window of
81695  *  at least DUK_LEXER_WINDOW_SIZE characters.
81696  *
81697  *  The main function duk__advance_bytes() is called at least once per every
81698  *  token so it has a major lexer/compiler performance impact.  There are two
81699  *  variants for the main duk__advance_bytes() algorithm: a sliding window
81700  *  approach which is slightly faster at the cost of larger code footprint,
81701  *  and a simple copying one.
81702  *
81703  *  Decoding directly from the source string would be another lexing option.
81704  *  But the lookup window based approach has the advantage of hiding the
81705  *  source string and its encoding effectively which gives more flexibility
81706  *  going forward to e.g. support chunked streaming of source from flash.
81707  *
81708  *  Decodes UTF-8/CESU-8 leniently with support for code points from U+0000 to
81709  *  U+10FFFF, causing an error if the input is unparseable.  Leniency means:
81710  *
81711  *    * Unicode code point validation is intentionally not performed,
81712  *      except to check that the codepoint does not exceed 0x10ffff.
81713  *
81714  *    * In particular, surrogate pairs are allowed and not combined, which
81715  *      allows source files to represent all SourceCharacters with CESU-8.
81716  *      Broken surrogate pairs are allowed, as ECMAScript does not mandate
81717  *      their validation.
81718  *
81719  *    * Allow non-shortest UTF-8 encodings.
81720  *
81721  *  Leniency here causes few security concerns because all character data is
81722  *  decoded into Unicode codepoints before lexer processing, and is then
81723  *  re-encoded into CESU-8.  The source can be parsed as strict UTF-8 with
81724  *  a compiler option.  However, ECMAScript source characters include -all-
81725  *  16-bit unsigned integer codepoints, so leniency seems to be appropriate.
81726  *
81727  *  Note that codepoints above the BMP are not strictly SourceCharacters,
81728  *  but the lexer still accepts them as such.  Before ending up in a string
81729  *  or an identifier name, codepoints above BMP are converted into surrogate
81730  *  pairs and then CESU-8 encoded, resulting in 16-bit Unicode data as
81731  *  expected by ECMAScript.
81732  *
81733  *  An alternative approach to dealing with invalid or partial sequences
81734  *  would be to skip them and replace them with e.g. the Unicode replacement
81735  *  character U+FFFD.  This has limited utility because a replacement character
81736  *  will most likely cause a parse error, unless it occurs inside a string.
81737  *  Further, ECMAScript source is typically pure ASCII.
81738  *
81739  *  See:
81740  *
81741  *     http://en.wikipedia.org/wiki/UTF-8
81742  *     http://en.wikipedia.org/wiki/CESU-8
81743  *     http://tools.ietf.org/html/rfc3629
81744  *     http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
81745  *
81746  *  Future work:
81747  *
81748  *    * Reject other invalid Unicode sequences (see Wikipedia entry for examples)
81749  *      in strict UTF-8 mode.
81750  *
81751  *    * Size optimize.  An attempt to use a 16-byte lookup table for the first
81752  *      byte resulted in a code increase though.
81753  *
81754  *    * Is checking against maximum 0x10ffff really useful?  4-byte encoding
81755  *      imposes a certain limit anyway.
81756  *
81757  *    * Support chunked streaming of source code.  Can be implemented either
81758  *      by streaming chunks of bytes or chunks of codepoints.
81759  */
81760 
81761 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
81762 DUK_LOCAL void duk__fill_lexer_buffer(duk_lexer_ctx *lex_ctx, duk_small_uint_t start_offset_bytes) {
81763 	duk_lexer_codepoint *cp, *cp_end;
81764 	duk_ucodepoint_t x;
81765 	duk_small_uint_t contlen;
81766 	const duk_uint8_t *p, *p_end;
81767 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81768 	duk_ucodepoint_t mincp;
81769 #endif
81770 	duk_int_t input_line;
81771 
81772 	/* Use temporaries and update lex_ctx only when finished. */
81773 	input_line = lex_ctx->input_line;
81774 	p = lex_ctx->input + lex_ctx->input_offset;
81775 	p_end = lex_ctx->input + lex_ctx->input_length;
81776 
81777 	cp = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->buffer + start_offset_bytes);
81778 	cp_end = lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE;
81779 
81780 	for (; cp != cp_end; cp++) {
81781 		cp->offset = (duk_size_t) (p - lex_ctx->input);
81782 		cp->line = input_line;
81783 
81784 		/* XXX: potential issue with signed pointers, p_end < p. */
81785 		if (DUK_UNLIKELY(p >= p_end)) {
81786 			/* If input_offset were assigned a negative value, it would
81787 			 * result in a large positive value.  Most likely it would be
81788 			 * larger than input_length and be caught here.  In any case
81789 			 * no memory unsafe behavior would happen.
81790 			 */
81791 			cp->codepoint = -1;
81792 			continue;
81793 		}
81794 
81795 		x = (duk_ucodepoint_t) (*p++);
81796 
81797 		/* Fast path. */
81798 
81799 		if (DUK_LIKELY(x < 0x80UL)) {
81800 			DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
81801 			if (DUK_UNLIKELY(x <= 0x000dUL)) {
81802 				if ((x == 0x000aUL) ||
81803 				    ((x == 0x000dUL) && (p >= p_end || *p != 0x000aUL))) {
81804 					/* lookup for 0x000a above assumes shortest encoding now */
81805 
81806 					/* E5 Section 7.3, treat the following as newlines:
81807 					 *   LF
81808 					 *   CR [not followed by LF]
81809 					 *   LS
81810 					 *   PS
81811 					 *
81812 					 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
81813 					 * the line number.
81814 					 */
81815 					input_line++;
81816 				}
81817 			}
81818 
81819 			cp->codepoint = (duk_codepoint_t) x;
81820 			continue;
81821 		}
81822 
81823 		/* Slow path. */
81824 
81825 		if (x < 0xc0UL) {
81826 			/* 10xx xxxx -> invalid */
81827 			goto error_encoding;
81828 		} else if (x < 0xe0UL) {
81829 			/* 110x xxxx   10xx xxxx  */
81830 			contlen = 1;
81831 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81832 			mincp = 0x80UL;
81833 #endif
81834 			x = x & 0x1fUL;
81835 		} else if (x < 0xf0UL) {
81836 			/* 1110 xxxx   10xx xxxx   10xx xxxx */
81837 			contlen = 2;
81838 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81839 			mincp = 0x800UL;
81840 #endif
81841 			x = x & 0x0fUL;
81842 		} else if (x < 0xf8UL) {
81843 			/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
81844 			contlen = 3;
81845 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81846 			mincp = 0x10000UL;
81847 #endif
81848 			x = x & 0x07UL;
81849 		} else {
81850 			/* no point in supporting encodings of 5 or more bytes */
81851 			goto error_encoding;
81852 		}
81853 
81854 		DUK_ASSERT(p_end >= p);
81855 		if ((duk_size_t) contlen > (duk_size_t) (p_end - p)) {
81856 			goto error_clipped;
81857 		}
81858 
81859 		while (contlen > 0) {
81860 			duk_small_uint_t y;
81861 			y = *p++;
81862 			if ((y & 0xc0U) != 0x80U) {
81863 				/* check that byte has the form 10xx xxxx */
81864 				goto error_encoding;
81865 			}
81866 			x = x << 6;
81867 			x += y & 0x3fUL;
81868 			contlen--;
81869 		}
81870 
81871 		/* check final character validity */
81872 
81873 		if (x > 0x10ffffUL) {
81874 			goto error_encoding;
81875 		}
81876 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81877 		if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
81878 			goto error_encoding;
81879 		}
81880 #endif
81881 
81882 		DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
81883 		if ((x == 0x2028UL) || (x == 0x2029UL)) {
81884 			input_line++;
81885 		}
81886 
81887 		cp->codepoint = (duk_codepoint_t) x;
81888 	}
81889 
81890 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
81891 	lex_ctx->input_line = input_line;
81892 	return;
81893 
81894  error_clipped:   /* clipped codepoint */
81895  error_encoding:  /* invalid codepoint encoding or codepoint */
81896 	lex_ctx->input_offset = (duk_size_t) (p - lex_ctx->input);
81897 	lex_ctx->input_line = input_line;
81898 
81899 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
81900 	DUK_WO_NORETURN(return;);
81901 }
81902 
81903 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
81904 	duk_small_uint_t used_bytes, avail_bytes;
81905 
81906 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
81907 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
81908 	DUK_ASSERT(lex_ctx->window >= lex_ctx->buffer);
81909 	DUK_ASSERT(lex_ctx->window < lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE);
81910 	DUK_ASSERT((duk_uint8_t *) lex_ctx->window + count_bytes <= (duk_uint8_t *) lex_ctx->buffer + DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint));
81911 
81912 	/* Zero 'count' is also allowed to make call sites easier.
81913 	 * Arithmetic in bytes generates better code in GCC.
81914 	 */
81915 
81916 	lex_ctx->window = (duk_lexer_codepoint *) (void *) ((duk_uint8_t *) lex_ctx->window + count_bytes);  /* avoid multiply */
81917 	used_bytes = (duk_small_uint_t) ((duk_uint8_t *) lex_ctx->window - (duk_uint8_t *) lex_ctx->buffer);
81918 	avail_bytes = DUK_LEXER_BUFFER_SIZE * sizeof(duk_lexer_codepoint) - used_bytes;
81919 	if (avail_bytes < (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint))) {
81920 		/* Not enough data to provide a full window, so "scroll" window to
81921 		 * start of buffer and fill up the rest.
81922 		 */
81923 		duk_memmove((void *) lex_ctx->buffer,
81924 		            (const void *) lex_ctx->window,
81925 		            (size_t) avail_bytes);
81926 		lex_ctx->window = lex_ctx->buffer;
81927 		duk__fill_lexer_buffer(lex_ctx, avail_bytes);
81928 	}
81929 }
81930 
81931 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
81932 	lex_ctx->window = lex_ctx->buffer;
81933 	duk__fill_lexer_buffer(lex_ctx, 0);
81934 }
81935 #else  /* DUK_USE_LEXER_SLIDING_WINDOW */
81936 DUK_LOCAL duk_codepoint_t duk__read_char(duk_lexer_ctx *lex_ctx) {
81937 	duk_ucodepoint_t x;
81938 	duk_small_uint_t len;
81939 	duk_small_uint_t i;
81940 	const duk_uint8_t *p;
81941 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81942 	duk_ucodepoint_t mincp;
81943 #endif
81944 	duk_size_t input_offset;
81945 
81946 	input_offset = lex_ctx->input_offset;
81947 	if (DUK_UNLIKELY(input_offset >= lex_ctx->input_length)) {
81948 		/* If input_offset were assigned a negative value, it would
81949 		 * result in a large positive value.  Most likely it would be
81950 		 * larger than input_length and be caught here.  In any case
81951 		 * no memory unsafe behavior would happen.
81952 		 */
81953 		return -1;
81954 	}
81955 
81956 	p = lex_ctx->input + input_offset;
81957 	x = (duk_ucodepoint_t) (*p);
81958 
81959 	if (DUK_LIKELY(x < 0x80UL)) {
81960 		/* 0xxx xxxx -> fast path */
81961 
81962 		/* input offset tracking */
81963 		lex_ctx->input_offset++;
81964 
81965 		DUK_ASSERT(x != 0x2028UL && x != 0x2029UL);  /* not LS/PS */
81966 		if (DUK_UNLIKELY(x <= 0x000dUL)) {
81967 			if ((x == 0x000aUL) ||
81968 			    ((x == 0x000dUL) && (lex_ctx->input_offset >= lex_ctx->input_length ||
81969 			                         lex_ctx->input[lex_ctx->input_offset] != 0x000aUL))) {
81970 				/* lookup for 0x000a above assumes shortest encoding now */
81971 
81972 				/* E5 Section 7.3, treat the following as newlines:
81973 				 *   LF
81974 				 *   CR [not followed by LF]
81975 				 *   LS
81976 				 *   PS
81977 				 *
81978 				 * For CR LF, CR is ignored if it is followed by LF, and the LF will bump
81979 				 * the line number.
81980 				 */
81981 				lex_ctx->input_line++;
81982 			}
81983 		}
81984 
81985 		return (duk_codepoint_t) x;
81986 	}
81987 
81988 	/* Slow path. */
81989 
81990 	if (x < 0xc0UL) {
81991 		/* 10xx xxxx -> invalid */
81992 		goto error_encoding;
81993 	} else if (x < 0xe0UL) {
81994 		/* 110x xxxx   10xx xxxx  */
81995 		len = 2;
81996 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
81997 		mincp = 0x80UL;
81998 #endif
81999 		x = x & 0x1fUL;
82000 	} else if (x < 0xf0UL) {
82001 		/* 1110 xxxx   10xx xxxx   10xx xxxx */
82002 		len = 3;
82003 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82004 		mincp = 0x800UL;
82005 #endif
82006 		x = x & 0x0fUL;
82007 	} else if (x < 0xf8UL) {
82008 		/* 1111 0xxx   10xx xxxx   10xx xxxx   10xx xxxx */
82009 		len = 4;
82010 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82011 		mincp = 0x10000UL;
82012 #endif
82013 		x = x & 0x07UL;
82014 	} else {
82015 		/* no point in supporting encodings of 5 or more bytes */
82016 		goto error_encoding;
82017 	}
82018 
82019 	DUK_ASSERT(lex_ctx->input_length >= lex_ctx->input_offset);
82020 	if ((duk_size_t) len > (duk_size_t) (lex_ctx->input_length - lex_ctx->input_offset)) {
82021 		goto error_clipped;
82022 	}
82023 
82024 	p++;
82025 	for (i = 1; i < len; i++) {
82026 		duk_small_uint_t y;
82027 		y = *p++;
82028 		if ((y & 0xc0U) != 0x80U) {
82029 			/* check that byte has the form 10xx xxxx */
82030 			goto error_encoding;
82031 		}
82032 		x = x << 6;
82033 		x += y & 0x3fUL;
82034 	}
82035 
82036 	/* check final character validity */
82037 
82038 	if (x > 0x10ffffUL) {
82039 		goto error_encoding;
82040 	}
82041 #if defined(DUK_USE_STRICT_UTF8_SOURCE)
82042 	if (x < mincp || (x >= 0xd800UL && x <= 0xdfffUL) || x == 0xfffeUL) {
82043 		goto error_encoding;
82044 	}
82045 #endif
82046 
82047 	/* input offset tracking */
82048 	lex_ctx->input_offset += len;
82049 
82050 	/* line tracking */
82051 	DUK_ASSERT(x != 0x000aUL && x != 0x000dUL);
82052 	if ((x == 0x2028UL) || (x == 0x2029UL)) {
82053 		lex_ctx->input_line++;
82054 	}
82055 
82056 	return (duk_codepoint_t) x;
82057 
82058  error_clipped:   /* clipped codepoint */
82059  error_encoding:  /* invalid codepoint encoding or codepoint */
82060 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_SOURCE_DECODE_FAILED);
82061 	DUK_WO_NORETURN(return 0;);
82062 }
82063 
82064 DUK_LOCAL void duk__advance_bytes(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_bytes) {
82065 	duk_small_uint_t keep_bytes;
82066 	duk_lexer_codepoint *cp, *cp_end;
82067 
82068 	DUK_ASSERT_DISABLE(count_bytes >= 0);  /* unsigned */
82069 	DUK_ASSERT(count_bytes <= (duk_small_uint_t) (DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint)));
82070 
82071 	/* Zero 'count' is also allowed to make call sites easier. */
82072 
82073 	keep_bytes = DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint) - count_bytes;
82074 	duk_memmove((void *) lex_ctx->window,
82075 	            (const void *) ((duk_uint8_t *) lex_ctx->window + count_bytes),
82076 	            (size_t) keep_bytes);
82077 
82078 	cp = (duk_lexer_codepoint *) ((duk_uint8_t *) lex_ctx->window + keep_bytes);
82079 	cp_end = lex_ctx->window + DUK_LEXER_WINDOW_SIZE;
82080 	for (; cp != cp_end; cp++) {
82081 		cp->offset = lex_ctx->input_offset;
82082 		cp->line = lex_ctx->input_line;
82083 		cp->codepoint = duk__read_char(lex_ctx);
82084 	}
82085 }
82086 
82087 DUK_LOCAL void duk__init_lexer_window(duk_lexer_ctx *lex_ctx) {
82088 	/* Call with count == DUK_LEXER_WINDOW_SIZE to fill buffer initially. */
82089 	duk__advance_bytes(lex_ctx, DUK_LEXER_WINDOW_SIZE * sizeof(duk_lexer_codepoint));  /* fill window */
82090 }
82091 #endif  /* DUK_USE_LEXER_SLIDING_WINDOW */
82092 
82093 DUK_LOCAL void duk__advance_chars(duk_lexer_ctx *lex_ctx, duk_small_uint_t count_chars) {
82094 	duk__advance_bytes(lex_ctx, count_chars * sizeof(duk_lexer_codepoint));
82095 }
82096 
82097 /*
82098  *  (Re)initialize the temporary byte buffer.  May be called extra times
82099  *  with little impact.
82100  */
82101 
82102 DUK_LOCAL void duk__initbuffer(duk_lexer_ctx *lex_ctx) {
82103 	/* Reuse buffer as is unless buffer has grown large. */
82104 	if (DUK_HBUFFER_DYNAMIC_GET_SIZE(lex_ctx->buf) < DUK_LEXER_TEMP_BUF_LIMIT) {
82105 		/* Keep current size */
82106 	} else {
82107 		duk_hbuffer_resize(lex_ctx->thr, lex_ctx->buf, DUK_LEXER_TEMP_BUF_LIMIT);
82108 	}
82109 
82110 	DUK_BW_INIT_WITHBUF(lex_ctx->thr, &lex_ctx->bw, lex_ctx->buf);
82111 }
82112 
82113 /*
82114  *  Append a Unicode codepoint to the temporary byte buffer.  Performs
82115  *  CESU-8 surrogate pair encoding for codepoints above the BMP.
82116  *  Existing surrogate pairs are allowed and also encoded into CESU-8.
82117  */
82118 
82119 DUK_LOCAL void duk__appendbuffer(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82120 	/*
82121 	 *  Since character data is only generated by decoding the source or by
82122 	 *  the compiler itself, we rely on the input codepoints being correct
82123 	 *  and avoid a check here.
82124 	 *
82125 	 *  Character data can also come here through decoding of Unicode
82126 	 *  escapes ("\udead\ubeef") so all 16-but unsigned values can be
82127 	 *  present, even when the source file itself is strict UTF-8.
82128 	 */
82129 	DUK_ASSERT(x >= 0 && x <= 0x10ffffL);
82130 
82131 	DUK_BW_WRITE_ENSURE_CESU8(lex_ctx->thr, &lex_ctx->bw, (duk_ucodepoint_t) x);
82132 }
82133 
82134 DUK_LOCAL void duk__appendbuffer_ascii(duk_lexer_ctx *lex_ctx, duk_codepoint_t x) {
82135 	/* ASCII characters can be emitted as a single byte without encoding
82136 	 * which matters for some fast paths.
82137 	 */
82138 	DUK_ASSERT(x >= 0 && x <= 0x7f);
82139 
82140 	DUK_BW_WRITE_ENSURE_U8(lex_ctx->thr, &lex_ctx->bw, (duk_uint8_t) x);
82141 }
82142 
82143 /*
82144  *  Intern the temporary byte buffer into a valstack slot
82145  *  (in practice, slot1 or slot2).
82146  */
82147 
82148 DUK_LOCAL duk_hstring *duk__internbuffer(duk_lexer_ctx *lex_ctx, duk_idx_t valstack_idx) {
82149 	DUK_ASSERT(valstack_idx == lex_ctx->slot1_idx || valstack_idx == lex_ctx->slot2_idx);
82150 
82151 	DUK_BW_PUSH_AS_STRING(lex_ctx->thr, &lex_ctx->bw);
82152 	duk_replace(lex_ctx->thr, valstack_idx);
82153 	return duk_known_hstring(lex_ctx->thr, valstack_idx);
82154 }
82155 
82156 /*
82157  *  Init lexer context
82158  */
82159 
82160 DUK_INTERNAL void duk_lexer_initctx(duk_lexer_ctx *lex_ctx) {
82161 	DUK_ASSERT(lex_ctx != NULL);
82162 
82163 	duk_memzero(lex_ctx, sizeof(*lex_ctx));
82164 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
82165 #if defined(DUK_USE_LEXER_SLIDING_WINDOW)
82166 	lex_ctx->window = NULL;
82167 #endif
82168 	lex_ctx->thr = NULL;
82169 	lex_ctx->input = NULL;
82170 	lex_ctx->buf = NULL;
82171 #endif
82172 }
82173 
82174 /*
82175  *  Set lexer input position and reinitialize lookup window.
82176  */
82177 
82178 DUK_INTERNAL void duk_lexer_getpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82179 	pt->offset = lex_ctx->window[0].offset;
82180 	pt->line = lex_ctx->window[0].line;
82181 }
82182 
82183 DUK_INTERNAL void duk_lexer_setpoint(duk_lexer_ctx *lex_ctx, duk_lexer_point *pt) {
82184 	DUK_ASSERT_DISABLE(pt->offset >= 0);  /* unsigned */
82185 	DUK_ASSERT(pt->line >= 1);
82186 	lex_ctx->input_offset = pt->offset;
82187 	lex_ctx->input_line = pt->line;
82188 	duk__init_lexer_window(lex_ctx);
82189 }
82190 
82191 /*
82192  *  Lexing helpers
82193  */
82194 
82195 /* Numeric value of a hex digit (also covers octal and decimal digits) or
82196  * -1 if not a valid hex digit.
82197  */
82198 DUK_LOCAL duk_codepoint_t duk__hexval_validate(duk_codepoint_t x) {
82199 	duk_small_int_t t;
82200 
82201 	/* Here 'x' is a Unicode codepoint */
82202 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82203 		t = duk_hex_dectab[x];
82204 		if (DUK_LIKELY(t >= 0)) {
82205 			return t;
82206 		}
82207 	}
82208 
82209 	return -1;
82210 }
82211 
82212 /* Just a wrapper for call sites where 'x' is known to be valid so
82213  * we assert for it before decoding.
82214  */
82215 DUK_LOCAL duk_codepoint_t duk__hexval(duk_codepoint_t x) {
82216 	duk_codepoint_t ret;
82217 
82218 	DUK_ASSERT((x >= DUK_ASC_0 && x <= DUK_ASC_9) ||
82219 	           (x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_F) ||
82220 	           (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_F));
82221 	ret = duk__hexval_validate(x);
82222 	DUK_ASSERT(ret >= 0 && ret <= 15);
82223 	return ret;
82224 }
82225 
82226 /* having this as a separate function provided a size benefit */
82227 DUK_LOCAL duk_bool_t duk__is_hex_digit(duk_codepoint_t x) {
82228 	if (DUK_LIKELY(x >= 0 && x <= 0xff)) {
82229 		return (duk_hex_dectab[x] >= 0);
82230 	}
82231 	return 0;
82232 }
82233 
82234 /* Parse a Unicode escape of the form \xHH, \uHHHH, or \u{H+}.  Shared by
82235  * source and RegExp parsing.
82236  */
82237 DUK_LOCAL duk_codepoint_t duk__lexer_parse_escape(duk_lexer_ctx *lex_ctx, duk_bool_t allow_es6) {
82238 	duk_small_int_t digits;  /* Initial value 2 or 4 for fixed length escapes, 0 for ES2015 \u{H+}. */
82239 	duk_codepoint_t escval;
82240 	duk_codepoint_t x;
82241 	duk_small_uint_t adv;
82242 
82243 	DUK_ASSERT(DUK__L0() == DUK_ASC_BACKSLASH);  /* caller responsibilities */
82244 	DUK_ASSERT(DUK__L1() == DUK_ASC_LC_X || DUK__L1() == DUK_ASC_LC_U);
82245 	DUK_UNREF(allow_es6);
82246 
82247 	adv = 2;
82248 	digits = 2;
82249 	if (DUK__L1() == DUK_ASC_LC_U) {
82250 		digits = 4;
82251 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
82252 		if (DUK__L2() == DUK_ASC_LCURLY && allow_es6) {
82253 			digits = 0;
82254 			adv = 3;
82255 		}
82256 #endif
82257 	}
82258 	DUK__ADVANCECHARS(lex_ctx, adv);
82259 
82260 	escval = 0;
82261 	for (;;) {
82262 		/* One of the escape forms: \xHH, \uHHHH, \u{H+}.
82263 		 * The 'digits' variable tracks parsing state and is
82264 		 * initialized to:
82265 		 *
82266 		 *   \xHH     2
82267 		 *   \uHH     4
82268 		 *   \u{H+}   0 first time, updated to -1 to indicate
82269 		 *            at least one digit has been parsed
82270 		 *
82271 		 * Octal parsing is handled separately because it can be
82272 		 * done with fixed lookahead and also has validation
82273 		 * rules which depend on the escape length (which is
82274 		 * variable).
82275 		 *
82276 		 * We don't need a specific check for x < 0 (end of
82277 		 * input) or duk_unicode_is_line_terminator(x)
82278 		 * because the 'dig' decode will fail and lead to a
82279 		 * SyntaxError.
82280 		 */
82281 		duk_codepoint_t dig;
82282 
82283 		x = DUK__L0();
82284 		DUK__ADVANCECHARS(lex_ctx, 1);
82285 
82286 		dig = duk__hexval_validate(x);
82287 		if (digits > 0) {
82288 			digits--;
82289 			if (dig < 0) {
82290 				goto fail_escape;
82291 			}
82292 			DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
82293 			escval = (escval << 4) + dig;
82294 			if (digits == 0) {
82295 				DUK_ASSERT(escval >= 0 && escval <= 0xffffL);
82296 				break;
82297 			}
82298 		} else {
82299 #if defined(DUK_USE_ES6_UNICODE_ESCAPE)
82300 			DUK_ASSERT(digits == 0 /* first time */ || digits == -1 /* others */);
82301 			if (dig >= 0) {
82302 				DUK_ASSERT(dig >= 0x00 && dig <= 0x0f);
82303 				escval = (escval << 4) + dig;
82304 				if (escval > 0x10ffffL) {
82305 					goto fail_escape;
82306 				}
82307 			} else if (x == DUK_ASC_RCURLY) {
82308 				if (digits == 0) {
82309 					/* Empty escape, \u{}. */
82310 					goto fail_escape;
82311 				}
82312 				DUK_ASSERT(escval >= 0 && escval <= 0x10ffffL);
82313 				break;
82314 			} else {
82315 				goto fail_escape;
82316 			}
82317 			digits = -1;  /* Indicate we have at least one digit. */
82318 #else  /* DUK_USE_ES6_UNICODE_ESCAPE */
82319 			DUK_ASSERT(0);  /* Never happens if \u{H+} support disabled. */
82320 #endif  /* DUK_USE_ES6_UNICODE_ESCAPE */
82321 		}
82322 	}
82323 
82324 	return escval;
82325 
82326  fail_escape:
82327 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
82328 	DUK_WO_NORETURN(return 0;);
82329 }
82330 
82331 /* Parse legacy octal escape of the form \N{1,3}, e.g. \0, \5, \0377.  Maximum
82332  * allowed value is \0377 (U+00FF), longest match is used.  Used for both string
82333  * RegExp octal escape parsing.  Window[0] must be the slash '\' and the first
82334  * digit must already be validated to be in [0-9] by the caller.
82335  */
82336 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) {
82337 	duk_codepoint_t cp;
82338 	duk_small_uint_t lookup_idx;
82339 	duk_small_uint_t adv;
82340 	duk_codepoint_t tmp;
82341 
82342 	DUK_ASSERT(out_adv != NULL);
82343 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 0) == DUK_ASC_BACKSLASH);
82344 	DUK_ASSERT(DUK__LOOKUP(lex_ctx, 1) >= DUK_ASC_0 && DUK__LOOKUP(lex_ctx, 1) <= DUK_ASC_9);
82345 
82346 	cp = 0;
82347 	tmp = 0;
82348 	for (lookup_idx = 1; lookup_idx <= 3; lookup_idx++) {
82349 		DUK_DDD(DUK_DDDPRINT("lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
82350 		tmp = DUK__LOOKUP(lex_ctx, lookup_idx);
82351 		if (tmp < DUK_ASC_0 || tmp > DUK_ASC_7) {
82352 			/* No more valid digits. */
82353 			break;
82354 		}
82355 		tmp = (cp << 3) + (tmp - DUK_ASC_0);
82356 		if (tmp > 0xff) {
82357 			/* Three digit octal escapes above \377 (= 0xff)
82358 			 * are not allowed.
82359 			 */
82360 			break;
82361 		}
82362 		cp = tmp;
82363 	}
82364 	DUK_DDD(DUK_DDDPRINT("final lookup_idx=%ld, cp=%ld", (long) lookup_idx, (long) cp));
82365 
82366 	adv = lookup_idx;
82367 	if (lookup_idx == 1) {
82368 		DUK_DDD(DUK_DDDPRINT("\\8 or \\9 -> treat as literal, accept in strict mode too"));
82369 		DUK_ASSERT(tmp == DUK_ASC_8 || tmp == DUK_ASC_9);
82370 		cp = tmp;
82371 		adv++;  /* correction to above, eat offending character */
82372 	} else if (lookup_idx == 2 && cp == 0) {
82373 		/* Note: 'foo\0bar' is OK in strict mode, but 'foo\00bar' is not.
82374 		 * It won't be interpreted as 'foo\u{0}0bar' but as a SyntaxError.
82375 		 */
82376 		DUK_DDD(DUK_DDDPRINT("\\0 -> accept in strict mode too"));
82377 	} else {
82378 		/* This clause also handles non-shortest zero, e.g. \00. */
82379 		if (reject_annex_b) {
82380 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> reject in strict-mode", (long) cp));
82381 			cp = -1;
82382 		} else {
82383 			DUK_DDD(DUK_DDDPRINT("non-zero octal literal %ld -> accepted", (long) cp));
82384 			DUK_ASSERT(cp >= 0 && cp <= 0xff);
82385 		}
82386 	}
82387 
82388 	*out_adv = adv;
82389 
82390 	DUK_ASSERT((cp >= 0 && cp <= 0xff) || (cp == -1 && reject_annex_b));
82391 	return cp;
82392 }
82393 
82394 /* XXX: move strict mode to lex_ctx? */
82395 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) {
82396 	duk_small_uint_t adv;
82397 
82398 	for (adv = 1 /* initial quote */ ;;) {
82399 		duk_codepoint_t x;
82400 
82401 		DUK__ADVANCECHARS(lex_ctx, adv);  /* eat opening quote on first loop */
82402 		x = DUK__L0();
82403 
82404 		adv = 1;
82405 		if (x == quote) {
82406 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing quote */
82407 			break;
82408 		} else if (x == '\\') {
82409 			/* DUK__L0        -> '\' char
82410 			 * DUK__L1 ... DUK__L5 -> more lookup
82411 			 */
82412 			duk_small_int_t emitcp = -1;
82413 
82414 			x = DUK__L1();
82415 
82416 			/* How much to advance before next loop. */
82417 			adv = 2;  /* note: long live range */
82418 
82419 			switch (x) {
82420 			case '\'':
82421 				emitcp = 0x0027;
82422 				break;
82423 			case '"':
82424 				emitcp = 0x0022;
82425 				break;
82426 			case '\\':
82427 				emitcp = 0x005c;
82428 				break;
82429 			case 'b':
82430 				emitcp = 0x0008;
82431 				break;
82432 			case 'f':
82433 				emitcp = 0x000c;
82434 				break;
82435 			case 'n':
82436 				emitcp = 0x000a;
82437 				break;
82438 			case 'r':
82439 				emitcp = 0x000d;
82440 				break;
82441 			case 't':
82442 				emitcp = 0x0009;
82443 				break;
82444 			case 'v':
82445 				emitcp = 0x000b;
82446 				break;
82447 			case 'x':
82448 			case 'u': {
82449 				duk_codepoint_t esc_cp;
82450 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
82451 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
82452 				adv = 0;
82453 				break;
82454 			}
82455 			default: {
82456 				if (duk_unicode_is_line_terminator(x)) {
82457 					/* line continuation */
82458 					if (x == 0x000d && DUK__L2() == 0x000a) {
82459 						/* CR LF again a special case */
82460 						adv = 3;  /* line terminator, CR, LF */
82461 					}
82462 				} else if (DUK__ISDIGIT(x)) {
82463 					/*
82464 					 *  Octal escape or zero escape:
82465 					 *    \0                                     (lookahead not OctalDigit)
82466 					 *    \1 ... \7                              (lookahead not OctalDigit)
82467 					 *    \ZeroToThree OctalDigit                (lookahead not OctalDigit)
82468 					 *    \FourToSeven OctalDigit                (no lookahead restrictions)
82469 					 *    \ZeroToThree OctalDigit OctalDigit     (no lookahead restrictions)
82470 					 *
82471 					 *  Zero escape is part of the standard syntax.  Octal escapes are
82472 					 *  defined in E5 Section B.1.2, and are only allowed in non-strict mode.
82473 					 *  Any other productions starting with a decimal digit are invalid
82474 					 *  but are in practice treated like identity escapes.
82475 					 *
82476 					 *  Parse octal (up to 3 digits) from the lookup window.
82477 					 */
82478 
82479 					emitcp = duk__lexer_parse_legacy_octal(lex_ctx, &adv, strict_mode /*reject_annex_b*/);
82480 					if (emitcp < 0) {
82481 						goto fail_escape;
82482 					}
82483 				} else if (x < 0) {
82484 					goto fail_unterminated;
82485 				} else {
82486 					/* escaped NonEscapeCharacter */
82487 					DUK__APPENDBUFFER(lex_ctx, x);
82488 				}
82489 			}  /* end default clause */
82490 			}  /* end switch */
82491 
82492 			/* Shared handling for single codepoint escapes. */
82493 			if (emitcp >= 0) {
82494 				DUK__APPENDBUFFER(lex_ctx, emitcp);
82495 			}
82496 
82497 			/* Track number of escapes; count not really needed but directive
82498 			 * prologues need to detect whether there were any escapes or line
82499 			 * continuations or not.
82500 			 */
82501 			out_token->num_escapes++;
82502 		} else if (x >= 0x20 && x <= 0x7f) {
82503 			/* Fast path for ASCII case, avoids line terminator
82504 			 * check and CESU-8 encoding.
82505 			 */
82506 			DUK_ASSERT(x >= 0);
82507 			DUK_ASSERT(!duk_unicode_is_line_terminator(x));
82508 			DUK_ASSERT(x != quote);
82509 			DUK_ASSERT(x != DUK_ASC_BACKSLASH);
82510 			DUK__APPENDBUFFER_ASCII(lex_ctx, x);
82511 		} else if (x < 0 || duk_unicode_is_line_terminator(x)) {
82512 			goto fail_unterminated;
82513 		} else {
82514 			/* Character which is part of the string but wasn't handled
82515 			 * by the fast path.
82516 			 */
82517 			DUK__APPENDBUFFER(lex_ctx, x);
82518 		}
82519 	} /* string parse loop */
82520 
82521 	return;
82522 
82523  fail_escape:
82524 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
82525 	DUK_WO_NORETURN(return;);
82526 
82527  fail_unterminated:
82528 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_STRING);
82529 	DUK_WO_NORETURN(return;);
82530 }
82531 
82532 /* Skip to end-of-line (or end-of-file), used for single line comments. */
82533 DUK_LOCAL void duk__lexer_skip_to_endofline(duk_lexer_ctx *lex_ctx) {
82534 	for (;;) {
82535 		duk_codepoint_t x;
82536 
82537 		x = DUK__L0();
82538 		if (x < 0 || duk_unicode_is_line_terminator(x)) {
82539 			break;
82540 		}
82541 		DUK__ADVANCECHARS(lex_ctx, 1);
82542 	}
82543 }
82544 
82545 /*
82546  *  Parse ECMAScript source InputElementDiv or InputElementRegExp
82547  *  (E5 Section 7), skipping whitespace, comments, and line terminators.
82548  *
82549  *  Possible results are:
82550  *    (1) a token
82551  *    (2) a line terminator (skipped)
82552  *    (3) a comment (skipped)
82553  *    (4) EOF
82554  *
82555  *  White space is automatically skipped from the current position (but
82556  *  not after the input element).  If input has already ended, returns
82557  *  DUK_TOK_EOF indefinitely.  If a parse error occurs, uses an DUK_ERROR()
82558  *  macro call (and hence a longjmp through current heap longjmp context).
82559  *  Comments and line terminator tokens are automatically skipped.
82560  *
82561  *  The input element being matched is determined by regexp_mode; if set,
82562  *  parses a InputElementRegExp, otherwise a InputElementDiv.  The
82563  *  difference between these are handling of productions starting with a
82564  *  forward slash.
82565  *
82566  *  If strict_mode is set, recognizes additional future reserved words
82567  *  specific to strict mode, and refuses to parse octal literals.
82568  *
82569  *  The matching strategy below is to (currently) use a six character
82570  *  lookup window to quickly determine which production is the -longest-
82571  *  matching one, and then parse that.  The top-level if-else clauses
82572  *  match the first character, and the code blocks for each clause
82573  *  handle -all- alternatives for that first character.  ECMAScript
82574  *  specification uses the "longest match wins" semantics, so the order
82575  *  of the if-clauses matters.
82576  *
82577  *  Misc notes:
82578  *
82579  *    * ECMAScript numeric literals do not accept a sign character.
82580  *      Consequently e.g. "-1.0" is parsed as two tokens: a negative
82581  *      sign and a positive numeric literal.  The compiler performs
82582  *      the negation during compilation, so this has no adverse impact.
82583  *
82584  *    * There is no token for "undefined": it is just a value available
82585  *      from the global object (or simply established by doing a reference
82586  *      to an undefined value).
82587  *
82588  *    * Some contexts want Identifier tokens, which are IdentifierNames
82589  *      excluding reserved words, while some contexts want IdentifierNames
82590  *      directly.  In the latter case e.g. "while" is interpreted as an
82591  *      identifier name, not a DUK_TOK_WHILE token.  The solution here is
82592  *      to provide both token types: DUK_TOK_WHILE goes to 't' while
82593  *      DUK_TOK_IDENTIFIER goes to 't_nores', and 'slot1' always contains
82594  *      the identifier / keyword name.
82595  *
82596  *    * Directive prologue needs to identify string literals such as
82597  *      "use strict" and 'use strict', which are sensitive to line
82598  *      continuations and escape sequences.  For instance, "use\u0020strict"
82599  *      is a valid directive but is distinct from "use strict".  The solution
82600  *      here is to decode escapes while tokenizing, but to keep track of the
82601  *      number of escapes.  Directive detection can then check that the
82602  *      number of escapes is zero.
82603  *
82604  *    * Multi-line comments with one or more internal LineTerminator are
82605  *      treated like a line terminator to comply with automatic semicolon
82606  *      insertion.
82607  */
82608 
82609 DUK_INTERNAL
82610 void duk_lexer_parse_js_input_element(duk_lexer_ctx *lex_ctx,
82611                                       duk_token *out_token,
82612                                       duk_bool_t strict_mode,
82613                                       duk_bool_t regexp_mode) {
82614 	duk_codepoint_t x;           /* temporary, must be signed and 32-bit to hold Unicode code points */
82615 	duk_small_uint_t advtok = 0; /* (advance << 8) + token_type, updated at function end,
82616 	                              * init is unnecessary but suppresses "may be used uninitialized" warnings.
82617 	                              */
82618 	duk_bool_t got_lineterm = 0;  /* got lineterm preceding non-whitespace, non-lineterm token */
82619 
82620 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
82621 		goto fail_token_limit;
82622 	}
82623 
82624 	out_token->t = DUK_TOK_EOF;
82625 	out_token->t_nores = DUK_TOK_INVALID;  /* marker: copy t if not changed */
82626 #if 0  /* not necessary to init, disabled for faster parsing */
82627 	out_token->num = DUK_DOUBLE_NAN;
82628 	out_token->str1 = NULL;
82629 	out_token->str2 = NULL;
82630 #endif
82631 	out_token->num_escapes = 0;
82632 	/* out_token->lineterm set by caller */
82633 
82634 	/* This would be nice, but parsing is faster without resetting the
82635 	 * value slots.  The only side effect is that references to temporary
82636 	 * string values may linger until lexing is finished; they're then
82637 	 * freed normally.
82638 	 */
82639 #if 0
82640 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot1_idx);
82641 	duk_to_undefined(lex_ctx->thr, lex_ctx->slot2_idx);
82642 #endif
82643 
82644 	/* 'advtok' indicates how much to advance and which token id to assign
82645 	 * at the end.  This shared functionality minimizes code size.  All
82646 	 * code paths are required to set 'advtok' to some value, so no default
82647 	 * init value is used.  Code paths calling DUK_ERROR() never return so
82648 	 * they don't need to set advtok.
82649 	 */
82650 
82651 	/*
82652 	 *  Matching order:
82653 	 *
82654 	 *    Punctuator first chars, also covers comments, regexps
82655 	 *    LineTerminator
82656 	 *    Identifier or reserved word, also covers null/true/false literals
82657 	 *    NumericLiteral
82658 	 *    StringLiteral
82659 	 *    EOF
82660 	 *
82661 	 *  The order does not matter as long as the longest match is
82662 	 *  always correctly identified.  There are order dependencies
82663 	 *  in the clauses, so it's not trivial to convert to a switch.
82664 	 */
82665 
82666  restart_lineupdate:
82667 	out_token->start_line = lex_ctx->window[0].line;
82668 
82669  restart:
82670 	out_token->start_offset = lex_ctx->window[0].offset;
82671 
82672 	x = DUK__L0();
82673 
82674 	switch (x) {
82675 	case DUK_ASC_SPACE:
82676 	case DUK_ASC_HT:  /* fast paths for space and tab */
82677 		DUK__ADVANCECHARS(lex_ctx, 1);
82678 		goto restart;
82679 	case DUK_ASC_LF:  /* LF line terminator; CR LF and Unicode lineterms are handled in slow path */
82680 		DUK__ADVANCECHARS(lex_ctx, 1);
82681 		got_lineterm = 1;
82682 		goto restart_lineupdate;
82683 #if defined(DUK_USE_SHEBANG_COMMENTS)
82684 	case DUK_ASC_HASH:  /* '#' */
82685 		if (DUK__L1() == DUK_ASC_EXCLAMATION && lex_ctx->window[0].offset == 0 &&
82686 		    (lex_ctx->flags & DUK_COMPILE_SHEBANG)) {
82687 			/* "Shebang" comment ('#! ...') on first line. */
82688 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
82689 			duk__lexer_skip_to_endofline(lex_ctx);
82690 			goto restart;  /* line terminator will be handled on next round */
82691 		}
82692 		goto fail_token;
82693 #endif  /* DUK_USE_SHEBANG_COMMENTS */
82694 	case DUK_ASC_SLASH:  /* '/' */
82695 		if (DUK__L1() == DUK_ASC_SLASH) {
82696 			/*
82697 			 *  E5 Section 7.4, allow SourceCharacter (which is any 16-bit
82698 			 *  code point).
82699 			 */
82700 
82701 			/* DUK__ADVANCECHARS(lex_ctx, 2) would be correct here, but not necessary */
82702 			duk__lexer_skip_to_endofline(lex_ctx);
82703 			goto restart;  /* line terminator will be handled on next round */
82704 		} else if (DUK__L1() == DUK_ASC_STAR) {
82705 			/*
82706 			 *  E5 Section 7.4.  If the multi-line comment contains a newline,
82707 			 *  it is treated like a single line terminator for automatic
82708 			 *  semicolon insertion.
82709 			 */
82710 
82711 			duk_bool_t last_asterisk = 0;
82712 			DUK__ADVANCECHARS(lex_ctx, 2);
82713 			for (;;) {
82714 				x = DUK__L0();
82715 				if (x < 0) {
82716 					goto fail_unterm_comment;
82717 				}
82718 				DUK__ADVANCECHARS(lex_ctx, 1);
82719 				if (last_asterisk && x == DUK_ASC_SLASH) {
82720 					break;
82721 				}
82722 				if (duk_unicode_is_line_terminator(x)) {
82723 					got_lineterm = 1;
82724 				}
82725 				last_asterisk = (x == DUK_ASC_STAR);
82726 			}
82727 			goto restart_lineupdate;
82728 		} else if (regexp_mode) {
82729 #if defined(DUK_USE_REGEXP_SUPPORT)
82730 			/*
82731 			 *  "/" followed by something in regexp mode.  See E5 Section 7.8.5.
82732 			 *
82733 			 *  RegExp parsing is a bit complex.  First, the regexp body is delimited
82734 			 *  by forward slashes, but the body may also contain forward slashes as
82735 			 *  part of an escape sequence or inside a character class (delimited by
82736 			 *  square brackets).  A mini state machine is used to implement these.
82737 			 *
82738 			 *  Further, an early (parse time) error must be thrown if the regexp
82739 			 *  would cause a run-time error when used in the expression new RegExp(...).
82740 			 *  Parsing here simply extracts the (candidate) regexp, and also accepts
82741 			 *  invalid regular expressions (which are delimited properly).  The caller
82742 			 *  (compiler) must perform final validation and regexp compilation.
82743 			 *
82744 			 *  RegExp first char may not be '/' (single line comment) or '*' (multi-
82745 			 *  line comment).  These have already been checked above, so there is no
82746 			 *  need below for special handling of the first regexp character as in
82747 			 *  the E5 productions.
82748 			 *
82749 			 *  About unicode escapes within regexp literals:
82750 			 *
82751 			 *      E5 Section 7.8.5 grammar does NOT accept \uHHHH escapes.
82752 			 *      However, Section 6 states that regexps accept the escapes,
82753 			 *      see paragraph starting with "In string literals...".
82754 			 *      The regexp grammar, which sees the decoded regexp literal
82755 			 *      (after lexical parsing) DOES have a \uHHHH unicode escape.
82756 			 *      So, for instance:
82757 			 *
82758 			 *          /\u1234/
82759 			 *
82760 			 *      should first be parsed by the lexical grammar as:
82761 			 *
82762 			 *          '\' 'u'      RegularExpressionBackslashSequence
82763 			 *          '1'          RegularExpressionNonTerminator
82764 			 *          '2'          RegularExpressionNonTerminator
82765 			 *          '3'          RegularExpressionNonTerminator
82766 			 *          '4'          RegularExpressionNonTerminator
82767 			 *
82768 			 *      and the escape itself is then parsed by the regexp engine.
82769 			 *      This is the current implementation.
82770 			 *
82771 			 *  Minor spec inconsistency:
82772 			 *
82773 			 *      E5 Section 7.8.5 RegularExpressionBackslashSequence is:
82774 			 *
82775 			 *         \ RegularExpressionNonTerminator
82776 			 *
82777 			 *      while Section A.1 RegularExpressionBackslashSequence is:
82778 			 *
82779 			 *         \ NonTerminator
82780 			 *
82781 			 *      The latter is not normative and a typo.
82782 			 *
82783 			 */
82784 
82785 			/* first, parse regexp body roughly */
82786 
82787 			duk_small_int_t state = 0;  /* 0=base, 1=esc, 2=class, 3=class+esc */
82788 
82789 			DUK__INITBUFFER(lex_ctx);
82790 			for (;;) {
82791 				DUK__ADVANCECHARS(lex_ctx, 1);  /* skip opening slash on first loop */
82792 				x = DUK__L0();
82793 				if (x < 0 || duk_unicode_is_line_terminator(x)) {
82794 					goto fail_unterm_regexp;
82795 				}
82796 				x = DUK__L0();  /* re-read to avoid spill / fetch */
82797 				if (state == 0) {
82798 					if (x == DUK_ASC_SLASH) {
82799 						DUK__ADVANCECHARS(lex_ctx, 1);  /* eat closing slash */
82800 						break;
82801 					} else if (x == DUK_ASC_BACKSLASH) {
82802 						state = 1;
82803 					} else if (x == DUK_ASC_LBRACKET) {
82804 						state = 2;
82805 					}
82806 				} else if (state == 1) {
82807 					state = 0;
82808 				} else if (state == 2) {
82809 					if (x == DUK_ASC_RBRACKET) {
82810 						state = 0;
82811 					} else if (x == DUK_ASC_BACKSLASH) {
82812 						state = 3;
82813 					}
82814 				} else { /* state == 3 */
82815 					state = 2;
82816 				}
82817 				DUK__APPENDBUFFER(lex_ctx, x);
82818 			}
82819 			out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
82820 
82821 			/* second, parse flags */
82822 
82823 			DUK__INITBUFFER(lex_ctx);
82824 			for (;;) {
82825 				x = DUK__L0();
82826 				if (!duk_unicode_is_identifier_part(x)) {
82827 					break;
82828 				}
82829 				x = DUK__L0();  /* re-read to avoid spill / fetch */
82830 				DUK__APPENDBUFFER(lex_ctx, x);
82831 				DUK__ADVANCECHARS(lex_ctx, 1);
82832 			}
82833 			out_token->str2 = duk__internbuffer(lex_ctx, lex_ctx->slot2_idx);
82834 
82835 			DUK__INITBUFFER(lex_ctx);  /* free some memory */
82836 
82837 			/* validation of the regexp is caller's responsibility */
82838 
82839 			advtok = DUK__ADVTOK(0, DUK_TOK_REGEXP);
82840 #else  /* DUK_USE_REGEXP_SUPPORT */
82841 			goto fail_regexp_support;
82842 #endif  /* DUK_USE_REGEXP_SUPPORT */
82843 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82844 			/* "/=" and not in regexp mode */
82845 			advtok = DUK__ADVTOK(2, DUK_TOK_DIV_EQ);
82846 		} else {
82847 			/* "/" and not in regexp mode */
82848 			advtok = DUK__ADVTOK(1, DUK_TOK_DIV);
82849 		}
82850 		break;
82851 	case DUK_ASC_LCURLY:  /* '{' */
82852 		advtok = DUK__ADVTOK(1, DUK_TOK_LCURLY);
82853 		break;
82854 	case DUK_ASC_RCURLY:  /* '}' */
82855 		advtok = DUK__ADVTOK(1, DUK_TOK_RCURLY);
82856 		break;
82857 	case DUK_ASC_LPAREN:  /* '(' */
82858 		advtok = DUK__ADVTOK(1, DUK_TOK_LPAREN);
82859 		break;
82860 	case DUK_ASC_RPAREN:  /* ')' */
82861 		advtok = DUK__ADVTOK(1, DUK_TOK_RPAREN);
82862 		break;
82863 	case DUK_ASC_LBRACKET:  /* '[' */
82864 		advtok = DUK__ADVTOK(1, DUK_TOK_LBRACKET);
82865 		break;
82866 	case DUK_ASC_RBRACKET:  /* ']' */
82867 		advtok = DUK__ADVTOK(1, DUK_TOK_RBRACKET);
82868 		break;
82869 	case DUK_ASC_PERIOD:  /* '.' */
82870 		if (DUK__ISDIGIT(DUK__L1())) {
82871 			/* Period followed by a digit can only start DecimalLiteral
82872 			 * (handled in slow path).  We could jump straight into the
82873 			 * DecimalLiteral handling but should avoid goto to inside
82874 			 * a block.
82875 			 */
82876 			goto slow_path;
82877 		}
82878 		advtok = DUK__ADVTOK(1, DUK_TOK_PERIOD);
82879 		break;
82880 	case DUK_ASC_SEMICOLON:  /* ';' */
82881 		advtok = DUK__ADVTOK(1, DUK_TOK_SEMICOLON);
82882 		break;
82883 	case DUK_ASC_COMMA:  /* ',' */
82884 		advtok = DUK__ADVTOK(1, DUK_TOK_COMMA);
82885 		break;
82886 	case DUK_ASC_LANGLE:  /* '<' */
82887 #if defined(DUK_USE_HTML_COMMENTS)
82888 		if (DUK__L1() == DUK_ASC_EXCLAMATION && DUK__L2() == DUK_ASC_MINUS && DUK__L3() == DUK_ASC_MINUS) {
82889 			/*
82890 			 *  ES2015: B.1.3, handle "<!--" SingleLineHTMLOpenComment
82891 			 */
82892 
82893 			/* DUK__ADVANCECHARS(lex_ctx, 4) would be correct here, but not necessary */
82894 			duk__lexer_skip_to_endofline(lex_ctx);
82895 			goto restart;  /* line terminator will be handled on next round */
82896 		}
82897 		else
82898 #endif  /* DUK_USE_HTML_COMMENTS */
82899 		if (DUK__L1() == DUK_ASC_LANGLE && DUK__L2() == DUK_ASC_EQUALS) {
82900 			advtok = DUK__ADVTOK(3, DUK_TOK_ALSHIFT_EQ);
82901 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82902 			advtok = DUK__ADVTOK(2, DUK_TOK_LE);
82903 		} else if (DUK__L1() == DUK_ASC_LANGLE) {
82904 			advtok = DUK__ADVTOK(2, DUK_TOK_ALSHIFT);
82905 		} else {
82906 			advtok = DUK__ADVTOK(1, DUK_TOK_LT);
82907 		}
82908 		break;
82909 	case DUK_ASC_RANGLE:  /* '>' */
82910 		if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE && DUK__L3() == DUK_ASC_EQUALS) {
82911 			advtok = DUK__ADVTOK(4, DUK_TOK_RSHIFT_EQ);
82912 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_RANGLE) {
82913 			advtok = DUK__ADVTOK(3, DUK_TOK_RSHIFT);
82914 		} else if (DUK__L1() == DUK_ASC_RANGLE && DUK__L2() == DUK_ASC_EQUALS) {
82915 			advtok = DUK__ADVTOK(3, DUK_TOK_ARSHIFT_EQ);
82916 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82917 			advtok = DUK__ADVTOK(2, DUK_TOK_GE);
82918 		} else if (DUK__L1() == DUK_ASC_RANGLE) {
82919 			advtok = DUK__ADVTOK(2, DUK_TOK_ARSHIFT);
82920 		} else {
82921 			advtok = DUK__ADVTOK(1, DUK_TOK_GT);
82922 		}
82923 		break;
82924 	case DUK_ASC_EQUALS:  /* '=' */
82925 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
82926 			advtok = DUK__ADVTOK(3, DUK_TOK_SEQ);
82927 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82928 			advtok = DUK__ADVTOK(2, DUK_TOK_EQ);
82929 		} else {
82930 			advtok = DUK__ADVTOK(1, DUK_TOK_EQUALSIGN);
82931 		}
82932 		break;
82933 	case DUK_ASC_EXCLAMATION:  /* '!' */
82934 		if (DUK__L1() == DUK_ASC_EQUALS && DUK__L2() == DUK_ASC_EQUALS) {
82935 			advtok = DUK__ADVTOK(3, DUK_TOK_SNEQ);
82936 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82937 			advtok = DUK__ADVTOK(2, DUK_TOK_NEQ);
82938 		} else {
82939 			advtok = DUK__ADVTOK(1, DUK_TOK_LNOT);
82940 		}
82941 		break;
82942 	case DUK_ASC_PLUS:  /* '+' */
82943 		if (DUK__L1() == DUK_ASC_PLUS) {
82944 			advtok = DUK__ADVTOK(2, DUK_TOK_INCREMENT);
82945 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82946 			advtok = DUK__ADVTOK(2, DUK_TOK_ADD_EQ);
82947 		} else {
82948 			advtok = DUK__ADVTOK(1, DUK_TOK_ADD);
82949 		}
82950 		break;
82951 	case DUK_ASC_MINUS:  /* '-' */
82952 #if defined(DUK_USE_HTML_COMMENTS)
82953 		if (got_lineterm && DUK__L1() == DUK_ASC_MINUS && DUK__L2() == DUK_ASC_RANGLE) {
82954 			/*
82955 			 *  ES2015: B.1.3, handle "-->" SingleLineHTMLCloseComment
82956 			 *  Only allowed:
82957 			 *  - on new line
82958 			 *  - preceded only by whitespace
82959 			 *  - preceded by end of multiline comment and optional whitespace
82960 			 *
82961 			 * Since whitespace generates no tokens, and multiline comments
82962 			 * are treated as a line ending, consulting `got_lineterm` is
82963 			 * sufficient to test for these three options.
82964 			 */
82965 
82966 			/* DUK__ADVANCECHARS(lex_ctx, 3) would be correct here, but not necessary */
82967 			duk__lexer_skip_to_endofline(lex_ctx);
82968 			goto restart;  /* line terminator will be handled on next round */
82969 		} else
82970 #endif  /* DUK_USE_HTML_COMMENTS */
82971 		if (DUK__L1() == DUK_ASC_MINUS) {
82972 			advtok = DUK__ADVTOK(2, DUK_TOK_DECREMENT);
82973 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
82974 			advtok = DUK__ADVTOK(2, DUK_TOK_SUB_EQ);
82975 		} else {
82976 			advtok = DUK__ADVTOK(1, DUK_TOK_SUB);
82977 		}
82978 		break;
82979 	case DUK_ASC_STAR:  /* '*' */
82980 #if defined(DUK_USE_ES7_EXP_OPERATOR)
82981 		if (DUK__L1() == DUK_ASC_STAR && DUK__L2() == DUK_ASC_EQUALS) {
82982 			advtok = DUK__ADVTOK(3, DUK_TOK_EXP_EQ);
82983 		} else if (DUK__L1() == DUK_ASC_STAR) {
82984 			advtok = DUK__ADVTOK(2, DUK_TOK_EXP);
82985 		} else
82986 #endif
82987 		if (DUK__L1() == DUK_ASC_EQUALS) {
82988 			advtok = DUK__ADVTOK(2, DUK_TOK_MUL_EQ);
82989 		} else {
82990 			advtok = DUK__ADVTOK(1, DUK_TOK_MUL);
82991 		}
82992 		break;
82993 	case DUK_ASC_PERCENT:  /* '%' */
82994 		if (DUK__L1() == DUK_ASC_EQUALS) {
82995 			advtok = DUK__ADVTOK(2, DUK_TOK_MOD_EQ);
82996 		} else {
82997 			advtok = DUK__ADVTOK(1, DUK_TOK_MOD);
82998 		}
82999 		break;
83000 	case DUK_ASC_AMP:  /* '&' */
83001 		if (DUK__L1() == DUK_ASC_AMP) {
83002 			advtok = DUK__ADVTOK(2, DUK_TOK_LAND);
83003 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83004 			advtok = DUK__ADVTOK(2, DUK_TOK_BAND_EQ);
83005 		} else {
83006 			advtok = DUK__ADVTOK(1, DUK_TOK_BAND);
83007 		}
83008 		break;
83009 	case DUK_ASC_PIPE:  /* '|' */
83010 		if (DUK__L1() == DUK_ASC_PIPE) {
83011 			advtok = DUK__ADVTOK(2, DUK_TOK_LOR);
83012 		} else if (DUK__L1() == DUK_ASC_EQUALS) {
83013 			advtok = DUK__ADVTOK(2, DUK_TOK_BOR_EQ);
83014 		} else {
83015 			advtok = DUK__ADVTOK(1, DUK_TOK_BOR);
83016 		}
83017 		break;
83018 	case DUK_ASC_CARET:  /* '^' */
83019 		if (DUK__L1() == DUK_ASC_EQUALS) {
83020 			advtok = DUK__ADVTOK(2, DUK_TOK_BXOR_EQ);
83021 		} else {
83022 			advtok = DUK__ADVTOK(1, DUK_TOK_BXOR);
83023 		}
83024 		break;
83025 	case DUK_ASC_TILDE:  /* '~' */
83026 		advtok = DUK__ADVTOK(1, DUK_TOK_BNOT);
83027 		break;
83028 	case DUK_ASC_QUESTION:  /* '?' */
83029 		advtok = DUK__ADVTOK(1, DUK_TOK_QUESTION);
83030 		break;
83031 	case DUK_ASC_COLON:  /* ':' */
83032 		advtok = DUK__ADVTOK(1, DUK_TOK_COLON);
83033 		break;
83034 	case DUK_ASC_DOUBLEQUOTE:    /* '"' */
83035 	case DUK_ASC_SINGLEQUOTE: {  /* '\'' */
83036 		DUK__INITBUFFER(lex_ctx);
83037 		duk__lexer_parse_string_literal(lex_ctx, out_token, x /*quote*/, strict_mode);
83038 		duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83039 		out_token->str1 = duk_known_hstring(lex_ctx->thr, lex_ctx->slot1_idx);
83040 
83041 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83042 
83043 		advtok = DUK__ADVTOK(0, DUK_TOK_STRING);
83044 		break;
83045 	}
83046 	default:
83047 		goto slow_path;
83048 	}  /* switch */
83049 
83050 	goto skip_slow_path;
83051 
83052  slow_path:
83053 	if (duk_unicode_is_line_terminator(x)) {
83054 		if (x == 0x000d && DUK__L1() == 0x000a) {
83055 			/*
83056 			 *  E5 Section 7.3: CR LF is detected as a single line terminator for
83057 			 *  line numbers.  Here we also detect it as a single line terminator
83058 			 *  token.
83059 			 */
83060 			DUK__ADVANCECHARS(lex_ctx, 2);
83061 		} else {
83062 			DUK__ADVANCECHARS(lex_ctx, 1);
83063 		}
83064 		got_lineterm = 1;
83065 		goto restart_lineupdate;
83066 	} else if (duk_unicode_is_identifier_start(x) || x == DUK_ASC_BACKSLASH) {
83067 		/*
83068 		 *  Parse an identifier and then check whether it is:
83069 		 *    - reserved word (keyword or other reserved word)
83070 		 *    - "null"  (NullLiteral)
83071 		 *    - "true"  (BooleanLiteral)
83072 		 *    - "false" (BooleanLiteral)
83073 		 *    - anything else => identifier
83074 		 *
83075 		 *  This does not follow the E5 productions cleanly, but is
83076 		 *  useful and compact.
83077 		 *
83078 		 *  Note that identifiers may contain Unicode escapes,
83079 		 *  see E5 Sections 6 and 7.6.  They must be decoded first,
83080 		 *  and the result checked against allowed characters.
83081 		 *  The above if-clause accepts an identifier start and an
83082 		 *  '\' character -- no other token can begin with a '\'.
83083 		 *
83084 		 *  Note that "get" and "set" are not reserved words in E5
83085 		 *  specification so they are recognized as plain identifiers
83086 		 *  (the tokens DUK_TOK_GET and DUK_TOK_SET are actually not
83087 		 *  used now).  The compiler needs to work around this.
83088 		 *
83089 		 *  Strictly speaking, following ECMAScript longest match
83090 		 *  specification, an invalid escape for the first character
83091 		 *  should cause a syntax error.  However, an invalid escape
83092 		 *  for IdentifierParts should just terminate the identifier
83093 		 *  early (longest match), and let the next tokenization
83094 		 *  fail.  For instance Rhino croaks with 'foo\z' when
83095 		 *  parsing the identifier.  This has little practical impact.
83096 		 */
83097 
83098 		duk_small_uint_t i, i_end;
83099 		duk_bool_t first = 1;
83100 		duk_hstring *str;
83101 
83102 		DUK__INITBUFFER(lex_ctx);
83103 		for (;;) {
83104 			/* re-lookup first char on first loop */
83105 			if (DUK__L0() == DUK_ASC_BACKSLASH) {
83106 				duk_codepoint_t esc_cp;
83107 				if (DUK__L1() != DUK_ASC_LC_U) {
83108 					goto fail_escape;
83109 				}
83110 				esc_cp = duk__lexer_parse_escape(lex_ctx, 1 /*allow_es6*/);
83111 				DUK__APPENDBUFFER(lex_ctx, esc_cp);
83112 
83113 				/* IdentifierStart is stricter than IdentifierPart, so if the first
83114 				 * character is escaped, must have a stricter check here.
83115 				 */
83116 				if (!(first ? duk_unicode_is_identifier_start(esc_cp) : duk_unicode_is_identifier_part(esc_cp))) {
83117 					goto fail_escape;
83118 				}
83119 
83120 				/* Track number of escapes: necessary for proper keyword
83121 				 * detection.
83122 				 */
83123 				out_token->num_escapes++;
83124 			} else {
83125 				/* Note: first character is checked against this.  But because
83126 				 * IdentifierPart includes all IdentifierStart characters, and
83127 				 * the first character (if unescaped) has already been checked
83128 				 * in the if condition, this is OK.
83129 				 */
83130 				if (!duk_unicode_is_identifier_part(DUK__L0())) {
83131 					break;
83132 				}
83133 				DUK__APPENDBUFFER(lex_ctx, DUK__L0());
83134 				DUK__ADVANCECHARS(lex_ctx, 1);
83135 			}
83136 			first = 0;
83137 		}
83138 
83139 		out_token->str1 = duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83140 		str = out_token->str1;
83141 		out_token->t_nores = DUK_TOK_IDENTIFIER;
83142 
83143 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83144 
83145 		/*
83146 		 *  Interned identifier is compared against reserved words, which are
83147 		 *  currently interned into the heap context.  See genbuiltins.py.
83148 		 *
83149 		 *  Note that an escape in the identifier disables recognition of
83150 		 *  keywords; e.g. "\u0069f = 1;" is a valid statement (assigns to
83151 		 *  identifier named "if").  This is not necessarily compliant,
83152 		 *  see test-dec-escaped-char-in-keyword.js.
83153 		 *
83154 		 *  Note: "get" and "set" are awkward.  They are not officially
83155 		 *  ReservedWords (and indeed e.g. "var set = 1;" is valid), and
83156 		 *  must come out as DUK_TOK_IDENTIFIER.  The compiler needs to
83157 		 *  work around this a bit.
83158 		 */
83159 
83160 		/* XXX: optimize by adding the token numbers directly into the
83161 		 * always interned duk_hstring objects (there should be enough
83162 		 * flag bits free for that)?
83163 		 */
83164 
83165 		i_end = (strict_mode ? DUK_STRIDX_END_RESERVED : DUK_STRIDX_START_STRICT_RESERVED);
83166 
83167 		advtok = DUK__ADVTOK(0, DUK_TOK_IDENTIFIER);
83168 		if (out_token->num_escapes == 0) {
83169 			for (i = DUK_STRIDX_START_RESERVED; i < i_end; i++) {
83170 				DUK_ASSERT_DISABLE(i >= 0);  /* unsigned */
83171 				DUK_ASSERT(i < DUK_HEAP_NUM_STRINGS);
83172 				if (DUK_HTHREAD_GET_STRING(lex_ctx->thr, i) == str) {
83173 					advtok = DUK__ADVTOK(0, DUK_STRIDX_TO_TOK(i));
83174 					break;
83175 				}
83176 			}
83177 		}
83178 	} else if (DUK__ISDIGIT(x) || (x == DUK_ASC_PERIOD)) {
83179 		/* Note: decimal number may start with a period, but must be followed by a digit */
83180 
83181 		/*
83182 		 *  Pre-parsing for decimal, hex, octal (both legacy and ES2015),
83183 		 *  and binary literals, followed by an actual parser step
83184 		 *  provided by numconv.
83185 		 *
83186 		 *  Note: the leading sign character ('+' or '-') is -not- part of
83187 		 *  the production in E5 grammar, and that the a DecimalLiteral
83188 		 *  starting with a '0' must be followed by a non-digit.
83189 		 *
83190 		 *  XXX: the two step parsing process is quite awkward, it would
83191 		 *  be more straightforward to allow numconv to parse the longest
83192 		 *  valid prefix (it already does that, it only needs to indicate
83193 		 *  where the input ended).  However, the lexer decodes characters
83194 		 *  using a limited lookup window, so this is not a trivial change.
83195 		 */
83196 
83197 		/* XXX: because of the final check below (that the literal is not
83198 		 * followed by a digit), this could maybe be simplified, if we bail
83199 		 * out early from a leading zero (and if there are no periods etc).
83200 		 * Maybe too complex.
83201 		 */
83202 
83203 		duk_double_t val;
83204 		duk_bool_t legacy_oct = 0;
83205 		duk_small_int_t state;  /* 0=before period/exp,
83206 		                         * 1=after period, before exp
83207 		                         * 2=after exp, allow '+' or '-'
83208 		                         * 3=after exp and exp sign
83209 		                         */
83210 		duk_small_uint_t s2n_flags;
83211 		duk_codepoint_t y, z;
83212 		duk_small_int_t s2n_radix = 10;
83213 		duk_small_uint_t pre_adv = 0;
83214 
83215 		DUK__INITBUFFER(lex_ctx);
83216 		y = DUK__L1();
83217 
83218 		if (x == DUK_ASC_0) {
83219 			z = DUK_LOWERCASE_CHAR_ASCII(y);
83220 
83221 			pre_adv = 2;  /* default for 0xNNN, 0oNNN, 0bNNN. */
83222 			if (z == DUK_ASC_LC_X) {
83223 				s2n_radix = 16;
83224 			} else if (z == DUK_ASC_LC_O) {
83225 				s2n_radix = 8;
83226 			} else if (z == DUK_ASC_LC_B) {
83227 				s2n_radix = 2;
83228 			} else {
83229 				pre_adv = 0;
83230 				if (DUK__ISDIGIT(y)) {
83231 					if (strict_mode) {
83232 						/* Reject octal like \07 but also octal-lookalike
83233 						 * decimal like \08 in strict mode.
83234 						 */
83235 						goto fail_number_literal;
83236 					} else {
83237 						/* Legacy OctalIntegerLiteral or octal-lookalice
83238 						 * decimal.  Deciding between the two happens below
83239 						 * in digit scanning.
83240 						 */
83241 						DUK__APPENDBUFFER(lex_ctx, x);
83242 						pre_adv = 1;
83243 						legacy_oct = 1;
83244 						s2n_radix = 8;  /* tentative unless conflicting digits found */
83245 					}
83246 				}
83247 			}
83248 		}
83249 
83250 		DUK__ADVANCECHARS(lex_ctx, pre_adv);
83251 
83252 		/* XXX: we could parse integers here directly, and fall back
83253 		 * to numconv only when encountering a fractional expression
83254 		 * or when an octal literal turned out to be decimal (0778 etc).
83255 		 */
83256 		state = 0;
83257 		for (;;) {
83258 			x = DUK__L0();  /* re-lookup curr char on first round */
83259 			if (DUK__ISDIGIT(x)) {
83260 				/* Note: intentionally allow leading zeroes here, as the
83261 				 * actual parser will check for them.
83262 				 */
83263 				if (state == 0 && legacy_oct && (x == DUK_ASC_8 || x == DUK_ASC_9)) {
83264 					/* Started out as an octal-lookalike
83265 					 * but interpreted as decimal, e.g.
83266 					 * '0779' -> 779.  This also means
83267 					 * that fractions are allowed, e.g.
83268 					 * '0779.123' is allowed but '0777.123'
83269 					 * is not!
83270 					 */
83271 					s2n_radix = 10;
83272 				}
83273 				if (state == 2) {
83274 					state = 3;
83275 				}
83276 			} else if (s2n_radix == 16 && DUK__ISHEXDIGIT(x)) {
83277 				/* Note: 'e' and 'E' are also accepted here. */
83278 				;
83279 			} else if (x == DUK_ASC_PERIOD) {
83280 				if (state >= 1 || s2n_radix != 10) {
83281 					break;
83282 				} else {
83283 					state = 1;
83284 				}
83285 			} else if (x == DUK_ASC_LC_E || x == DUK_ASC_UC_E) {
83286 				if (state >= 2 || s2n_radix != 10) {
83287 					break;
83288 				} else {
83289 					state = 2;
83290 				}
83291 			} else if (x == DUK_ASC_MINUS || x == DUK_ASC_PLUS) {
83292 				if (state != 2) {
83293 					break;
83294 				} else {
83295 					state = 3;
83296 				}
83297 			} else {
83298 				break;
83299 			}
83300 			DUK__APPENDBUFFER(lex_ctx, x);
83301 			DUK__ADVANCECHARS(lex_ctx, 1);
83302 		}
83303 
83304 		/* XXX: better coercion */
83305 		(void) duk__internbuffer(lex_ctx, lex_ctx->slot1_idx);
83306 
83307 		if (s2n_radix != 10) {
83308 			/* For bases other than 10, integer only. */
83309 			s2n_flags = DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
83310 		} else {
83311 			s2n_flags = DUK_S2N_FLAG_ALLOW_EXP |
83312 			            DUK_S2N_FLAG_ALLOW_FRAC |
83313 			            DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
83314 			            DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
83315 			            DUK_S2N_FLAG_ALLOW_LEADING_ZERO;
83316 		}
83317 
83318 		duk_dup(lex_ctx->thr, lex_ctx->slot1_idx);
83319 		duk_numconv_parse(lex_ctx->thr, s2n_radix, s2n_flags);
83320 		val = duk_to_number_m1(lex_ctx->thr);
83321 		if (DUK_ISNAN(val)) {
83322 			goto fail_number_literal;
83323 		}
83324 		duk_replace(lex_ctx->thr, lex_ctx->slot1_idx);  /* could also just pop? */
83325 
83326 		DUK__INITBUFFER(lex_ctx);  /* free some memory */
83327 
83328 		/* Section 7.8.3 (note): NumericLiteral must be followed by something other than
83329 		 * IdentifierStart or DecimalDigit.
83330 		 */
83331 
83332 		if (DUK__ISDIGIT(DUK__L0()) || duk_unicode_is_identifier_start(DUK__L0())) {
83333 			goto fail_number_literal;
83334 		}
83335 
83336 		out_token->num = val;
83337 		advtok = DUK__ADVTOK(0, DUK_TOK_NUMBER);
83338 	} else if (duk_unicode_is_whitespace(DUK__LOOKUP(lex_ctx, 0))) {
83339 		DUK__ADVANCECHARS(lex_ctx, 1);
83340 		goto restart;
83341 	} else if (x < 0) {
83342 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
83343 	} else {
83344 		goto fail_token;
83345 	}
83346  skip_slow_path:
83347 
83348 	/*
83349 	 *  Shared exit path
83350 	 */
83351 
83352 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
83353 	out_token->t = advtok & 0xff;
83354 	if (out_token->t_nores == DUK_TOK_INVALID) {
83355 		out_token->t_nores = out_token->t;
83356 	}
83357 	out_token->lineterm = got_lineterm;
83358 
83359 	/* Automatic semicolon insertion is allowed if a token is preceded
83360 	 * by line terminator(s), or terminates a statement list (right curly
83361 	 * or EOF).
83362 	 */
83363 	if (got_lineterm || out_token->t == DUK_TOK_RCURLY || out_token->t == DUK_TOK_EOF) {
83364 		out_token->allow_auto_semi = 1;
83365 	} else {
83366 		out_token->allow_auto_semi = 0;
83367 	}
83368 
83369 	return;
83370 
83371  fail_token_limit:
83372 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
83373 	DUK_WO_NORETURN(return;);
83374 
83375  fail_token:
83376 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_TOKEN);
83377 	DUK_WO_NORETURN(return;);
83378 
83379  fail_number_literal:
83380 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_NUMBER_LITERAL);
83381 	DUK_WO_NORETURN(return;);
83382 
83383  fail_escape:
83384 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_ESCAPE);
83385 	DUK_WO_NORETURN(return;);
83386 
83387  fail_unterm_regexp:
83388 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_REGEXP);
83389 	DUK_WO_NORETURN(return;);
83390 
83391  fail_unterm_comment:
83392 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_COMMENT);
83393 	DUK_WO_NORETURN(return;);
83394 
83395 #if !defined(DUK_USE_REGEXP_SUPPORT)
83396  fail_regexp_support:
83397 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_REGEXP_SUPPORT_DISABLED);
83398 	DUK_WO_NORETURN(return;);
83399 #endif
83400 }
83401 
83402 #if defined(DUK_USE_REGEXP_SUPPORT)
83403 
83404 /*
83405  *  Parse a RegExp token.  The grammar is described in E5 Section 15.10.
83406  *  Terminal constructions (such as quantifiers) are parsed directly here.
83407  *
83408  *  0xffffffffU is used as a marker for "infinity" in quantifiers.  Further,
83409  *  DUK__MAX_RE_QUANT_DIGITS limits the maximum number of digits that
83410  *  will be accepted for a quantifier.
83411  */
83412 
83413 DUK_INTERNAL void duk_lexer_parse_re_token(duk_lexer_ctx *lex_ctx, duk_re_token *out_token) {
83414 	duk_small_uint_t advtok = 0;  /* init is unnecessary but suppresses "may be used uninitialized" warnings */
83415 	duk_codepoint_t x, y;
83416 
83417 	if (++lex_ctx->token_count >= lex_ctx->token_limit) {
83418 		goto fail_token_limit;
83419 	}
83420 
83421 	duk_memzero(out_token, sizeof(*out_token));
83422 
83423 	x = DUK__L0();
83424 	y = DUK__L1();
83425 
83426 	DUK_DDD(DUK_DDDPRINT("parsing regexp token, L0=%ld, L1=%ld", (long) x, (long) y));
83427 
83428 	switch (x) {
83429 	case DUK_ASC_PIPE: {
83430 		advtok = DUK__ADVTOK(1, DUK_RETOK_DISJUNCTION);
83431 		break;
83432 	}
83433 	case DUK_ASC_CARET: {
83434 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_START);
83435 		break;
83436 	}
83437 	case DUK_ASC_DOLLAR: {
83438 		advtok = DUK__ADVTOK(1, DUK_RETOK_ASSERT_END);
83439 		break;
83440 	}
83441 	case DUK_ASC_QUESTION: {
83442 		out_token->qmin = 0;
83443 		out_token->qmax = 1;
83444 		if (y == DUK_ASC_QUESTION) {
83445 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83446 			out_token->greedy = 0;
83447 		} else {
83448 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83449 			out_token->greedy = 1;
83450 		}
83451 		break;
83452 	}
83453 	case DUK_ASC_STAR: {
83454 		out_token->qmin = 0;
83455 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83456 		if (y == DUK_ASC_QUESTION) {
83457 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83458 			out_token->greedy = 0;
83459 		} else {
83460 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83461 			out_token->greedy = 1;
83462 		}
83463 		break;
83464 	}
83465 	case DUK_ASC_PLUS: {
83466 		out_token->qmin = 1;
83467 		out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83468 		if (y == DUK_ASC_QUESTION) {
83469 			advtok = DUK__ADVTOK(2, DUK_RETOK_QUANTIFIER);
83470 			out_token->greedy = 0;
83471 		} else {
83472 			advtok = DUK__ADVTOK(1, DUK_RETOK_QUANTIFIER);
83473 			out_token->greedy = 1;
83474 		}
83475 		break;
83476 	}
83477 	case DUK_ASC_LCURLY: {
83478 		/* Production allows 'DecimalDigits', including leading zeroes */
83479 		duk_uint32_t val1 = 0;
83480 		duk_uint32_t val2 = DUK_RE_QUANTIFIER_INFINITE;
83481 		duk_small_int_t digits = 0;
83482 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83483 		duk_lexer_point lex_pt;
83484 #endif
83485 
83486 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83487 		/* Store lexer position, restoring if quantifier is invalid. */
83488 		DUK_LEXER_GETPOINT(lex_ctx, &lex_pt);
83489 #endif
83490 
83491 		for (;;) {
83492 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat '{' on entry */
83493 			x = DUK__L0();
83494 			if (DUK__ISDIGIT(x)) {
83495 				digits++;
83496 				val1 = val1 * 10 + (duk_uint32_t) duk__hexval(x);
83497 			} else if (x == DUK_ASC_COMMA) {
83498 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
83499 					goto invalid_quantifier;
83500 				}
83501 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
83502 					goto invalid_quantifier;
83503 				}
83504 				if (DUK__L1() == DUK_ASC_RCURLY) {
83505 					/* form: { DecimalDigits , }, val1 = min count */
83506 					if (digits == 0) {
83507 						goto invalid_quantifier;
83508 					}
83509 					out_token->qmin = val1;
83510 					out_token->qmax = DUK_RE_QUANTIFIER_INFINITE;
83511 					DUK__ADVANCECHARS(lex_ctx, 2);
83512 					break;
83513 				}
83514 				val2 = val1;
83515 				val1 = 0;
83516 				digits = 0;  /* not strictly necessary because of lookahead '}' above */
83517 			} else if (x == DUK_ASC_RCURLY) {
83518 				if (digits > DUK__MAX_RE_QUANT_DIGITS) {
83519 					goto invalid_quantifier;
83520 				}
83521 				if (digits == 0) {
83522 					goto invalid_quantifier;
83523 				}
83524 				if (val2 != DUK_RE_QUANTIFIER_INFINITE) {
83525 					/* val2 = min count, val1 = max count */
83526 					out_token->qmin = val2;
83527 					out_token->qmax = val1;
83528 				} else {
83529 					/* val1 = count */
83530 					out_token->qmin = val1;
83531 					out_token->qmax = val1;
83532 				}
83533 				DUK__ADVANCECHARS(lex_ctx, 1);
83534 				break;
83535 			} else {
83536 				goto invalid_quantifier;
83537 			}
83538 		}
83539 		if (DUK__L0() == DUK_ASC_QUESTION) {
83540 			out_token->greedy = 0;
83541 			DUK__ADVANCECHARS(lex_ctx, 1);
83542 		} else {
83543 			out_token->greedy = 1;
83544 		}
83545 		advtok = DUK__ADVTOK(0, DUK_RETOK_QUANTIFIER);
83546 		break;
83547  invalid_quantifier:
83548 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83549 		/* Failed to match the quantifier, restore lexer and parse
83550 		 * opening brace as a literal.
83551 		 */
83552 		DUK_LEXER_SETPOINT(lex_ctx, &lex_pt);
83553 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
83554 		out_token->num = DUK_ASC_LCURLY;
83555 #else
83556 		goto fail_quantifier;
83557 #endif
83558 		break;
83559 	}
83560 	case DUK_ASC_PERIOD: {
83561 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_PERIOD);
83562 		break;
83563 	}
83564 	case DUK_ASC_BACKSLASH: {
83565 		/* The E5.1 specification does not seem to allow IdentifierPart characters
83566 		 * to be used as identity escapes.  Unfortunately this includes '$', which
83567 		 * cannot be escaped as '\$'; it needs to be escaped e.g. as '\u0024'.
83568 		 * Many other implementations (including V8 and Rhino, for instance) do
83569 		 * accept '\$' as a valid identity escape, which is quite pragmatic, and
83570 		 * ES2015 Annex B relaxes the rules to allow these (and other) real world forms.
83571 		 */
83572 
83573 		advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);  /* default: char escape (two chars) */
83574 		if (y == DUK_ASC_LC_B) {
83575 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_WORD_BOUNDARY);
83576 		} else if (y == DUK_ASC_UC_B) {
83577 			advtok = DUK__ADVTOK(2, DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY);
83578 		} else if (y == DUK_ASC_LC_F) {
83579 			out_token->num = 0x000c;
83580 		} else if (y == DUK_ASC_LC_N) {
83581 			out_token->num = 0x000a;
83582 		} else if (y == DUK_ASC_LC_T) {
83583 			out_token->num = 0x0009;
83584 		} else if (y == DUK_ASC_LC_R) {
83585 			out_token->num = 0x000d;
83586 		} else if (y == DUK_ASC_LC_V) {
83587 			out_token->num = 0x000b;
83588 		} else if (y == DUK_ASC_LC_C) {
83589 			x = DUK__L2();
83590 			if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
83591 			    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
83592 				out_token->num = (duk_uint32_t) (x % 32);
83593 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_CHAR);
83594 			} else {
83595 				goto fail_escape;
83596 			}
83597 		} else if (y == DUK_ASC_LC_X || y == DUK_ASC_LC_U) {
83598 			/* The token value is the Unicode codepoint without
83599 			 * it being decode into surrogate pair characters
83600 			 * here.  The \u{H+} is only allowed in Unicode mode
83601 			 * which we don't support yet.
83602 			 */
83603 			out_token->num = (duk_uint32_t) duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
83604 			advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_CHAR);
83605 		} else if (y == DUK_ASC_LC_D) {
83606 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_DIGIT);
83607 		} else if (y == DUK_ASC_UC_D) {
83608 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_DIGIT);
83609 		} else if (y == DUK_ASC_LC_S) {
83610 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WHITE);
83611 		} else if (y == DUK_ASC_UC_S) {
83612 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WHITE);
83613 		} else if (y == DUK_ASC_LC_W) {
83614 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_WORD_CHAR);
83615 		} else if (y == DUK_ASC_UC_W) {
83616 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_NOT_WORD_CHAR);
83617 		} else if (DUK__ISDIGIT(y)) {
83618 			/* E5 Section 15.10.2.11 */
83619 			if (y == DUK_ASC_0) {
83620 				if (DUK__ISDIGIT(DUK__L2())) {
83621 					goto fail_escape;
83622 				}
83623 				out_token->num = 0x0000;
83624 				advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_CHAR);
83625 			} else {
83626 				/* XXX: shared parsing? */
83627 				duk_uint32_t val = 0;
83628 				duk_small_int_t i;
83629 				for (i = 0; ; i++) {
83630 					if (i >= DUK__MAX_RE_DECESC_DIGITS) {
83631 						goto fail_escape;
83632 					}
83633 					DUK__ADVANCECHARS(lex_ctx, 1);  /* eat backslash on entry */
83634 					x = DUK__L0();
83635 					if (!DUK__ISDIGIT(x)) {
83636 						break;
83637 					}
83638 					val = val * 10 + (duk_uint32_t) duk__hexval(x);
83639 				}
83640 				/* DUK__L0() cannot be a digit, because the loop doesn't terminate if it is */
83641 				advtok = DUK__ADVTOK(0, DUK_RETOK_ATOM_BACKREFERENCE);
83642 				out_token->num = val;
83643 			}
83644 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83645 		} else if (y >= 0) {
83646 			/* For ES2015 Annex B, accept any source character as identity
83647 			 * escape except 'c' which is used for control characters.
83648 			 * http://www.ecma-international.org/ecma-262/6.0/#sec-regular-expressions-patterns
83649 			 * Careful not to match end-of-buffer (<0) here.
83650 			 * This is not yet full ES2015 Annex B because cases above
83651 			 * (like hex escape) won't backtrack.
83652 			 */
83653 			DUK_ASSERT(y != DUK_ASC_LC_C);  /* covered above */
83654 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
83655 		} else if ((y >= 0 && !duk_unicode_is_identifier_part(y)) ||
83656 		           y == DUK_UNICODE_CP_ZWNJ ||
83657 		           y == DUK_UNICODE_CP_ZWJ) {
83658 			/* For ES5.1 identity escapes are not allowed for identifier
83659 			 * parts.  This conflicts with a lot of real world code as this
83660 			 * doesn't e.g. allow escaping a dollar sign as /\$/, see
83661 			 * test-regexp-identity-escape-dollar.js.
83662 			 */
83663 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
83664 			out_token->num = (duk_uint32_t) y;
83665 		} else {
83666 			goto fail_escape;
83667 		}
83668 		break;
83669 	}
83670 	case DUK_ASC_LPAREN: {
83671 		/* XXX: naming is inconsistent: ATOM_END_GROUP ends an ASSERT_START_LOOKAHEAD */
83672 
83673 		if (y == DUK_ASC_QUESTION) {
83674 			if (DUK__L2() == DUK_ASC_EQUALS) {
83675 				/* (?= */
83676 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_POS_LOOKAHEAD);
83677 			} else if (DUK__L2() == DUK_ASC_EXCLAMATION) {
83678 				/* (?! */
83679 				advtok = DUK__ADVTOK(3, DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD);
83680 			} else if (DUK__L2() == DUK_ASC_COLON) {
83681 				/* (?: */
83682 				advtok = DUK__ADVTOK(3, DUK_RETOK_ATOM_START_NONCAPTURE_GROUP);
83683 			} else {
83684 				goto fail_group;
83685 			}
83686 		} else {
83687 			/* ( */
83688 			advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CAPTURE_GROUP);
83689 		}
83690 		break;
83691 	}
83692 	case DUK_ASC_RPAREN: {
83693 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_END_GROUP);
83694 		break;
83695 	}
83696 	case DUK_ASC_LBRACKET: {
83697 		/*
83698 		 *  To avoid creating a heavy intermediate value for the list of ranges,
83699 		 *  only the start token ('[' or '[^') is parsed here.  The regexp
83700 		 *  compiler parses the ranges itself.
83701 		 */
83702 
83703 		/* XXX: with DUK_USE_ES6_REGEXP_SYNTAX we should allow left bracket
83704 		 * literal too, but it's not easy to parse without backtracking.
83705 		 */
83706 
83707 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_START_CHARCLASS);
83708 		if (y == DUK_ASC_CARET) {
83709 			advtok = DUK__ADVTOK(2, DUK_RETOK_ATOM_START_CHARCLASS_INVERTED);
83710 		}
83711 		break;
83712 	}
83713 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
83714 	case DUK_ASC_RCURLY:
83715 	case DUK_ASC_RBRACKET: {
83716 		/* Although these could be parsed as PatternCharacters unambiguously (here),
83717 		 * E5 Section 15.10.1 grammar explicitly forbids these as PatternCharacters.
83718 		 */
83719 		goto fail_invalid_char;
83720 		break;
83721 	}
83722 #endif
83723 	case -1: {
83724 		/* EOF */
83725 		advtok = DUK__ADVTOK(0, DUK_TOK_EOF);
83726 		break;
83727 	}
83728 	default: {
83729 		/* PatternCharacter, all excluded characters are matched by cases above */
83730 		advtok = DUK__ADVTOK(1, DUK_RETOK_ATOM_CHAR);
83731 		out_token->num = (duk_uint32_t) x;
83732 		break;
83733 	}
83734 	}
83735 
83736 	/*
83737 	 *  Shared exit path
83738 	 */
83739 
83740 	DUK__ADVANCEBYTES(lex_ctx, advtok >> 8);
83741 	out_token->t = advtok & 0xff;
83742 	return;
83743 
83744  fail_token_limit:
83745 	DUK_ERROR_RANGE(lex_ctx->thr, DUK_STR_TOKEN_LIMIT);
83746 	DUK_WO_NORETURN(return;);
83747 
83748  fail_escape:
83749 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
83750 	DUK_WO_NORETURN(return;);
83751 
83752  fail_group:
83753 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_GROUP);
83754 	DUK_WO_NORETURN(return;);
83755 
83756 #if !defined(DUK_USE_ES6_REGEXP_SYNTAX)
83757  fail_invalid_char:
83758 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_CHARACTER);
83759 	DUK_WO_NORETURN(return;);
83760 
83761  fail_quantifier:
83762 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_QUANTIFIER);
83763 	DUK_WO_NORETURN(return;);
83764 #endif
83765 }
83766 
83767 /*
83768  *  Special parser for character classes; calls callback for every
83769  *  range parsed and returns the number of ranges present.
83770  */
83771 
83772 /* XXX: this duplicates functionality in duk_regexp.c where a similar loop is
83773  * required anyway.  We could use that BUT we need to update the regexp compiler
83774  * 'nranges' too.  Work this out a bit more cleanly to save space.
83775  */
83776 
83777 /* XXX: the handling of character range detection is a bit convoluted.
83778  * Try to simplify and make smaller.
83779  */
83780 
83781 /* XXX: logic for handling character ranges is now incorrect, it will accept
83782  * e.g. [\d-z] whereas it should croak from it?  SMJS accepts this too, though.
83783  *
83784  * Needs a read through and a lot of additional tests.
83785  */
83786 
83787 DUK_LOCAL
83788 void duk__emit_u16_direct_ranges(duk_lexer_ctx *lex_ctx,
83789                                  duk_re_range_callback gen_range,
83790                                  void *userdata,
83791                                  const duk_uint16_t *ranges,
83792                                  duk_small_int_t num) {
83793 	const duk_uint16_t *ranges_end;
83794 
83795 	DUK_UNREF(lex_ctx);
83796 
83797 	ranges_end = ranges + num;
83798 	while (ranges < ranges_end) {
83799 		/* mark range 'direct', bypass canonicalization (see Wiki) */
83800 		gen_range(userdata, (duk_codepoint_t) ranges[0], (duk_codepoint_t) ranges[1], 1);
83801 		ranges += 2;
83802 	}
83803 }
83804 
83805 DUK_INTERNAL void duk_lexer_parse_re_ranges(duk_lexer_ctx *lex_ctx, duk_re_range_callback gen_range, void *userdata) {
83806 	duk_codepoint_t start = -1;
83807 	duk_codepoint_t ch;
83808 	duk_codepoint_t x;
83809 	duk_bool_t dash = 0;
83810 	duk_small_uint_t adv = 0;
83811 
83812 	DUK_DD(DUK_DDPRINT("parsing regexp ranges"));
83813 
83814 	for (;;) {
83815 		DUK__ADVANCECHARS(lex_ctx, adv);
83816 		adv = 1;
83817 
83818 		x = DUK__L0();
83819 
83820 		ch = -1;  /* not strictly necessary, but avoids "uninitialized variable" warnings */
83821 		DUK_UNREF(ch);
83822 
83823 		if (x < 0) {
83824 			goto fail_unterm_charclass;
83825 		} else if (x == DUK_ASC_RBRACKET) {
83826 			if (start >= 0) {
83827 				gen_range(userdata, start, start, 0);
83828 			}
83829 			DUK__ADVANCECHARS(lex_ctx, 1);  /* eat ']' before finishing */
83830 			break;
83831 		} else if (x == DUK_ASC_MINUS) {
83832 			if (start >= 0 && !dash && DUK__L1() != DUK_ASC_RBRACKET) {
83833 				/* '-' as a range indicator */
83834 				dash = 1;
83835 				continue;
83836 			} else {
83837 				/* '-' verbatim */
83838 				ch = x;
83839 			}
83840 		} else if (x == DUK_ASC_BACKSLASH) {
83841 			/*
83842 			 *  The escapes are same as outside a character class, except that \b has a
83843 			 *  different meaning, and \B and backreferences are prohibited (see E5
83844 			 *  Section 15.10.2.19).  However, it's difficult to share code because we
83845 			 *  handle e.g. "\n" very differently: here we generate a single character
83846 			 *  range for it.
83847 			 */
83848 
83849 			/* XXX: ES2015 surrogate pair handling. */
83850 
83851 			x = DUK__L1();
83852 
83853 			adv = 2;
83854 
83855 			if (x == DUK_ASC_LC_B) {
83856 				/* Note: '\b' in char class is different than outside (assertion),
83857 				 * '\B' is not allowed and is caught by the duk_unicode_is_identifier_part()
83858 				 * check below.
83859 				 */
83860 				ch = 0x0008;
83861 			} else if (x == DUK_ASC_LC_F) {
83862 				ch = 0x000c;
83863 			} else if (x == DUK_ASC_LC_N) {
83864 				ch = 0x000a;
83865 			} else if (x == DUK_ASC_LC_T) {
83866 				ch = 0x0009;
83867 			} else if (x == DUK_ASC_LC_R) {
83868 				ch = 0x000d;
83869 			} else if (x == DUK_ASC_LC_V) {
83870 				ch = 0x000b;
83871 			} else if (x == DUK_ASC_LC_C) {
83872 				x = DUK__L2();
83873 				adv = 3;
83874 				if ((x >= DUK_ASC_LC_A && x <= DUK_ASC_LC_Z) ||
83875 				    (x >= DUK_ASC_UC_A && x <= DUK_ASC_UC_Z)) {
83876 					ch = (x % 32);
83877 				} else {
83878 					goto fail_escape;
83879 				}
83880 			} else if (x == DUK_ASC_LC_X || x == DUK_ASC_LC_U) {
83881 				/* The \u{H+} form is only allowed in Unicode mode which
83882 				 * we don't support yet.
83883 				 */
83884 				ch = duk__lexer_parse_escape(lex_ctx, 0 /*allow_es6*/);
83885 				adv = 0;
83886 			} else if (x == DUK_ASC_LC_D) {
83887 				duk__emit_u16_direct_ranges(lex_ctx,
83888 				                            gen_range,
83889 				                            userdata,
83890 				                            duk_unicode_re_ranges_digit,
83891 				                            sizeof(duk_unicode_re_ranges_digit) / sizeof(duk_uint16_t));
83892 				ch = -1;
83893 			} else if (x == DUK_ASC_UC_D) {
83894 				duk__emit_u16_direct_ranges(lex_ctx,
83895 				                            gen_range,
83896 				                            userdata,
83897 				                            duk_unicode_re_ranges_not_digit,
83898 				                            sizeof(duk_unicode_re_ranges_not_digit) / sizeof(duk_uint16_t));
83899 				ch = -1;
83900 			} else if (x == DUK_ASC_LC_S) {
83901 				duk__emit_u16_direct_ranges(lex_ctx,
83902 				                            gen_range,
83903 				                            userdata,
83904 				                            duk_unicode_re_ranges_white,
83905 				                            sizeof(duk_unicode_re_ranges_white) / sizeof(duk_uint16_t));
83906 				ch = -1;
83907 			} else if (x == DUK_ASC_UC_S) {
83908 				duk__emit_u16_direct_ranges(lex_ctx,
83909 				                            gen_range,
83910 				                            userdata,
83911 				                            duk_unicode_re_ranges_not_white,
83912 				                            sizeof(duk_unicode_re_ranges_not_white) / sizeof(duk_uint16_t));
83913 				ch = -1;
83914 			} else if (x == DUK_ASC_LC_W) {
83915 				duk__emit_u16_direct_ranges(lex_ctx,
83916 				                            gen_range,
83917 				                            userdata,
83918 				                            duk_unicode_re_ranges_wordchar,
83919 				                            sizeof(duk_unicode_re_ranges_wordchar) / sizeof(duk_uint16_t));
83920 				ch = -1;
83921 			} else if (x == DUK_ASC_UC_W) {
83922 				duk__emit_u16_direct_ranges(lex_ctx,
83923 				                            gen_range,
83924 				                            userdata,
83925 				                            duk_unicode_re_ranges_not_wordchar,
83926 				                            sizeof(duk_unicode_re_ranges_not_wordchar) / sizeof(duk_uint16_t));
83927 				ch = -1;
83928 			} else if (DUK__ISDIGIT(x)) {
83929 				/* DecimalEscape, only \0 is allowed, no leading
83930 				 * zeroes are allowed.
83931 				 *
83932 				 * ES2015 Annex B also allows (maximal match) legacy
83933 				 * octal escapes up to \377 and \8 and \9 are
83934 				 * accepted as literal '8' and '9', also in strict mode.
83935 				 */
83936 
83937 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83938 				ch = duk__lexer_parse_legacy_octal(lex_ctx, &adv, 0 /*reject_annex_b*/);
83939 				DUK_ASSERT(ch >= 0);  /* no rejections */
83940 #else
83941 				if (x == DUK_ASC_0 && !DUK__ISDIGIT(DUK__L2())) {
83942 					ch = 0x0000;
83943 				} else {
83944 					goto fail_escape;
83945 				}
83946 #endif
83947 #if defined(DUK_USE_ES6_REGEXP_SYNTAX)
83948 			} else if (x >= 0) {
83949 				/* IdentityEscape: ES2015 Annex B allows almost all
83950 				 * source characters here.  Match anything except
83951 				 * EOF here.
83952 				 */
83953 				ch = x;
83954 #else  /* DUK_USE_ES6_REGEXP_SYNTAX */
83955 			} else if (!duk_unicode_is_identifier_part(x)) {
83956 				/* IdentityEscape: ES5.1 doesn't allow identity escape
83957 				 * for identifier part characters, which conflicts with
83958 				 * some real world code.  For example, it doesn't allow
83959 				 * /[\$]/ which is awkward.
83960 				 */
83961 				ch = x;
83962 #endif  /* DUK_USE_ES6_REGEXP_SYNTAX */
83963 			} else {
83964 				goto fail_escape;
83965 			}
83966 		} else {
83967 			/* character represents itself */
83968 			ch = x;
83969 		}
83970 
83971 		/* ch is a literal character here or -1 if parsed entity was
83972 		 * an escape such as "\s".
83973 		 */
83974 
83975 		if (ch < 0) {
83976 			/* multi-character sets not allowed as part of ranges, see
83977 			 * E5 Section 15.10.2.15, abstract operation CharacterRange.
83978 			 */
83979 			if (start >= 0) {
83980 				if (dash) {
83981 					goto fail_range;
83982 				} else {
83983 					gen_range(userdata, start, start, 0);
83984 					start = -1;
83985 					/* dash is already 0 */
83986 				}
83987 			}
83988 		} else {
83989 			if (start >= 0) {
83990 				if (dash) {
83991 					if (start > ch) {
83992 						goto fail_range;
83993 					}
83994 					gen_range(userdata, start, ch, 0);
83995 					start = -1;
83996 					dash = 0;
83997 				} else {
83998 					gen_range(userdata, start, start, 0);
83999 					start = ch;
84000 					/* dash is already 0 */
84001 				}
84002 			} else {
84003 				start = ch;
84004 			}
84005 		}
84006 	}
84007 
84008 	return;
84009 
84010  fail_escape:
84011 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_REGEXP_ESCAPE);
84012 	DUK_WO_NORETURN(return;);
84013 
84014  fail_range:
84015 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_INVALID_RANGE);
84016 	DUK_WO_NORETURN(return;);
84017 
84018  fail_unterm_charclass:
84019 	DUK_ERROR_SYNTAX(lex_ctx->thr, DUK_STR_UNTERMINATED_CHARCLASS);
84020 	DUK_WO_NORETURN(return;);
84021 }
84022 
84023 #endif  /* DUK_USE_REGEXP_SUPPORT */
84024 
84025 /* automatic undefs */
84026 #undef DUK__ADVANCEBYTES
84027 #undef DUK__ADVANCECHARS
84028 #undef DUK__ADVTOK
84029 #undef DUK__APPENDBUFFER
84030 #undef DUK__APPENDBUFFER_ASCII
84031 #undef DUK__INITBUFFER
84032 #undef DUK__ISDIGIT
84033 #undef DUK__ISDIGIT03
84034 #undef DUK__ISDIGIT47
84035 #undef DUK__ISHEXDIGIT
84036 #undef DUK__ISOCTDIGIT
84037 #undef DUK__L0
84038 #undef DUK__L1
84039 #undef DUK__L2
84040 #undef DUK__L3
84041 #undef DUK__L4
84042 #undef DUK__L5
84043 #undef DUK__LOOKUP
84044 #undef DUK__MAX_RE_DECESC_DIGITS
84045 #undef DUK__MAX_RE_QUANT_DIGITS
84046 #line 1 "duk_numconv.c"
84047 /*
84048  *  Number-to-string and string-to-number conversions.
84049  *
84050  *  Slow path number-to-string and string-to-number conversion is based on
84051  *  a Dragon4 variant, with fast paths for small integers.  Big integer
84052  *  arithmetic is needed for guaranteeing that the conversion is correct
84053  *  and uses a minimum number of digits.  The big number arithmetic has a
84054  *  fixed maximum size and does not require dynamic allocations.
84055  *
84056  *  See: doc/number-conversion.rst.
84057  */
84058 
84059 /* #include duk_internal.h -> already included */
84060 
84061 #define DUK__IEEE_DOUBLE_EXP_BIAS  1023
84062 #define DUK__IEEE_DOUBLE_EXP_MIN   (-1022)   /* biased exp == 0 -> denormal, exp -1022 */
84063 
84064 #define DUK__DIGITCHAR(x)  duk_lc_digits[(x)]
84065 
84066 /*
84067  *  Tables generated with util/gennumdigits.py.
84068  *
84069  *  duk__str2num_digits_for_radix indicates, for each radix, how many input
84070  *  digits should be considered significant for string-to-number conversion.
84071  *  The input is also padded to this many digits to give the Dragon4
84072  *  conversion enough (apparent) precision to work with.
84073  *
84074  *  duk__str2num_exp_limits indicates, for each radix, the radix-specific
84075  *  minimum/maximum exponent values (for a Dragon4 integer mantissa)
84076  *  below and above which the number is guaranteed to underflow to zero
84077  *  or overflow to Infinity.  This allows parsing to keep bigint values
84078  *  bounded.
84079  */
84080 
84081 DUK_LOCAL const duk_uint8_t duk__str2num_digits_for_radix[] = {
84082 	69, 44, 35, 30, 27, 25, 23, 22, 20, 20,    /* 2 to 11 */
84083 	20, 19, 19, 18, 18, 17, 17, 17, 16, 16,    /* 12 to 21 */
84084 	16, 16, 16, 15, 15, 15, 15, 15, 15, 14,    /* 22 to 31 */
84085 	14, 14, 14, 14, 14                         /* 31 to 36 */
84086 };
84087 
84088 typedef struct {
84089 	duk_int16_t upper;
84090 	duk_int16_t lower;
84091 } duk__exp_limits;
84092 
84093 DUK_LOCAL const duk__exp_limits duk__str2num_exp_limits[] = {
84094 	{ 957, -1147 }, { 605, -725 },  { 479, -575 },  { 414, -496 },
84095 	{ 372, -446 },  { 342, -411 },  { 321, -384 },  { 304, -364 },
84096 	{ 291, -346 },  { 279, -334 },  { 268, -323 },  { 260, -312 },
84097 	{ 252, -304 },  { 247, -296 },  { 240, -289 },  { 236, -283 },
84098 	{ 231, -278 },  { 227, -273 },  { 223, -267 },  { 220, -263 },
84099 	{ 216, -260 },  { 213, -256 },  { 210, -253 },  { 208, -249 },
84100 	{ 205, -246 },  { 203, -244 },  { 201, -241 },  { 198, -239 },
84101 	{ 196, -237 },  { 195, -234 },  { 193, -232 },  { 191, -230 },
84102 	{ 190, -228 },  { 188, -226 },  { 187, -225 },
84103 };
84104 
84105 /*
84106  *  Limited functionality bigint implementation.
84107  *
84108  *  Restricted to non-negative numbers with less than 32 * DUK__BI_MAX_PARTS bits,
84109  *  with the caller responsible for ensuring this is never exceeded.  No memory
84110  *  allocation (except stack) is needed for bigint computation.  Operations
84111  *  have been tailored for number conversion needs.
84112  *
84113  *  Argument order is "assignment order", i.e. target first, then arguments:
84114  *  x <- y * z  -->  duk__bi_mul(x, y, z);
84115  */
84116 
84117 /* This upper value has been experimentally determined; debug build will check
84118  * bigint size with assertions.
84119  */
84120 #define DUK__BI_MAX_PARTS  37  /* 37x32 = 1184 bits */
84121 
84122 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84123 #define DUK__BI_PRINT(name,x)  duk__bi_print((name),(x))
84124 #else
84125 #define DUK__BI_PRINT(name,x)
84126 #endif
84127 
84128 /* Current size is about 152 bytes. */
84129 typedef struct {
84130 	duk_small_int_t n;
84131 	duk_uint32_t v[DUK__BI_MAX_PARTS];  /* low to high */
84132 } duk__bigint;
84133 
84134 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
84135 DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) {
84136 	/* Overestimate required size; debug code so not critical to be tight. */
84137 	char buf[DUK__BI_MAX_PARTS * 9 + 64];
84138 	char *p = buf;
84139 	duk_small_int_t i;
84140 
84141 	/* No NUL term checks in this debug code. */
84142 	p += DUK_SPRINTF(p, "%p n=%ld", (void *) x, (long) x->n);
84143 	if (x->n == 0) {
84144 		p += DUK_SPRINTF(p, " 0");
84145 	}
84146 	for (i = x->n - 1; i >= 0; i--) {
84147 		p += DUK_SPRINTF(p, " %08lx", (unsigned long) x->v[i]);
84148 	}
84149 
84150 	DUK_DDD(DUK_DDDPRINT("%s: %s", (const char *) name, (const char *) buf));
84151 }
84152 #endif
84153 
84154 #if defined(DUK_USE_ASSERTIONS)
84155 DUK_LOCAL duk_small_int_t duk__bi_is_valid(duk__bigint *x) {
84156 	return (duk_small_int_t)
84157 	       ( ((x->n >= 0) && (x->n <= DUK__BI_MAX_PARTS)) /* is valid size */ &&
84158 	         ((x->n == 0) || (x->v[x->n - 1] != 0)) /* is normalized */ );
84159 }
84160 #endif
84161 
84162 DUK_LOCAL void duk__bi_normalize(duk__bigint *x) {
84163 	duk_small_int_t i;
84164 
84165 	for (i = x->n - 1; i >= 0; i--) {
84166 		if (x->v[i] != 0) {
84167 			break;
84168 		}
84169 	}
84170 
84171 	/* Note: if 'x' is zero, x->n becomes 0 here */
84172 	x->n = i + 1;
84173 	DUK_ASSERT(duk__bi_is_valid(x));
84174 }
84175 
84176 /* x <- y */
84177 DUK_LOCAL void duk__bi_copy(duk__bigint *x, duk__bigint *y) {
84178 	duk_small_int_t n;
84179 
84180 	n = y->n;
84181 	x->n = n;
84182 	/* No need to special case n == 0. */
84183 	duk_memcpy((void *) x->v, (const void *) y->v, (size_t) (sizeof(duk_uint32_t) * (size_t) n));
84184 }
84185 
84186 DUK_LOCAL void duk__bi_set_small(duk__bigint *x, duk_uint32_t v) {
84187 	if (v == 0U) {
84188 		x->n = 0;
84189 	} else {
84190 		x->n = 1;
84191 		x->v[0] = v;
84192 	}
84193 	DUK_ASSERT(duk__bi_is_valid(x));
84194 }
84195 
84196 /* Return value: <0  <=>  x < y
84197  *                0  <=>  x == y
84198  *               >0  <=>  x > y
84199  */
84200 DUK_LOCAL int duk__bi_compare(duk__bigint *x, duk__bigint *y) {
84201 	duk_small_int_t i, nx, ny;
84202 	duk_uint32_t tx, ty;
84203 
84204 	DUK_ASSERT(duk__bi_is_valid(x));
84205 	DUK_ASSERT(duk__bi_is_valid(y));
84206 
84207 	nx = x->n;
84208 	ny = y->n;
84209 	if (nx > ny) {
84210 		goto ret_gt;
84211 	}
84212 	if (nx < ny) {
84213 		goto ret_lt;
84214 	}
84215 	for (i = nx - 1; i >= 0; i--) {
84216 		tx = x->v[i];
84217 		ty = y->v[i];
84218 
84219 		if (tx > ty) {
84220 			goto ret_gt;
84221 		}
84222 		if (tx < ty) {
84223 			goto ret_lt;
84224 		}
84225 	}
84226 
84227 	return 0;
84228 
84229  ret_gt:
84230 	return 1;
84231 
84232  ret_lt:
84233 	return -1;
84234 }
84235 
84236 /* x <- y + z */
84237 #if defined(DUK_USE_64BIT_OPS)
84238 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84239 	duk_uint64_t tmp;
84240 	duk_small_int_t i, ny, nz;
84241 
84242 	DUK_ASSERT(duk__bi_is_valid(y));
84243 	DUK_ASSERT(duk__bi_is_valid(z));
84244 
84245 	if (z->n > y->n) {
84246 		duk__bigint *t;
84247 		t = y; y = z; z = t;
84248 	}
84249 	DUK_ASSERT(y->n >= z->n);
84250 
84251 	ny = y->n; nz = z->n;
84252 	tmp = 0U;
84253 	for (i = 0; i < ny; i++) {
84254 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84255 		tmp += y->v[i];
84256 		if (i < nz) {
84257 			tmp += z->v[i];
84258 		}
84259 		x->v[i] = (duk_uint32_t) (tmp & 0xffffffffUL);
84260 		tmp = tmp >> 32;
84261 	}
84262 	if (tmp != 0U) {
84263 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84264 		x->v[i++] = (duk_uint32_t) tmp;
84265 	}
84266 	x->n = i;
84267 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
84268 
84269 	/* no need to normalize */
84270 	DUK_ASSERT(duk__bi_is_valid(x));
84271 }
84272 #else  /* DUK_USE_64BIT_OPS */
84273 DUK_LOCAL void duk__bi_add(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84274 	duk_uint32_t carry, tmp1, tmp2;
84275 	duk_small_int_t i, ny, nz;
84276 
84277 	DUK_ASSERT(duk__bi_is_valid(y));
84278 	DUK_ASSERT(duk__bi_is_valid(z));
84279 
84280 	if (z->n > y->n) {
84281 		duk__bigint *t;
84282 		t = y; y = z; z = t;
84283 	}
84284 	DUK_ASSERT(y->n >= z->n);
84285 
84286 	ny = y->n; nz = z->n;
84287 	carry = 0U;
84288 	for (i = 0; i < ny; i++) {
84289 		/* Carry is detected based on wrapping which relies on exact 32-bit
84290 		 * types.
84291 		 */
84292 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84293 		tmp1 = y->v[i];
84294 		tmp2 = tmp1;
84295 		if (i < nz) {
84296 			tmp2 += z->v[i];
84297 		}
84298 
84299 		/* Careful with carry condition:
84300 		 *  - If carry not added: 0x12345678 + 0 + 0xffffffff = 0x12345677 (< 0x12345678)
84301 		 *  - If carry added:     0x12345678 + 1 + 0xffffffff = 0x12345678 (== 0x12345678)
84302 		 */
84303 		if (carry) {
84304 			tmp2++;
84305 			carry = (tmp2 <= tmp1 ? 1U : 0U);
84306 		} else {
84307 			carry = (tmp2 < tmp1 ? 1U : 0U);
84308 		}
84309 
84310 		x->v[i] = tmp2;
84311 	}
84312 	if (carry) {
84313 		DUK_ASSERT(i < DUK__BI_MAX_PARTS);
84314 		DUK_ASSERT(carry == 1U);
84315 		x->v[i++] = carry;
84316 	}
84317 	x->n = i;
84318 	DUK_ASSERT(x->n <= DUK__BI_MAX_PARTS);
84319 
84320 	/* no need to normalize */
84321 	DUK_ASSERT(duk__bi_is_valid(x));
84322 }
84323 #endif  /* DUK_USE_64BIT_OPS */
84324 
84325 /* x <- y + z */
84326 DUK_LOCAL void duk__bi_add_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84327 	duk__bigint tmp;
84328 
84329 	DUK_ASSERT(duk__bi_is_valid(y));
84330 
84331 	/* XXX: this could be optimized; there is only one call site now though */
84332 	duk__bi_set_small(&tmp, z);
84333 	duk__bi_add(x, y, &tmp);
84334 
84335 	DUK_ASSERT(duk__bi_is_valid(x));
84336 }
84337 
84338 #if 0  /* unused */
84339 /* x <- x + y, use t as temp */
84340 DUK_LOCAL void duk__bi_add_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84341 	duk__bi_add(t, x, y);
84342 	duk__bi_copy(x, t);
84343 }
84344 #endif
84345 
84346 /* x <- y - z, require x >= y => z >= 0, i.e. y >= z */
84347 #if defined(DUK_USE_64BIT_OPS)
84348 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84349 	duk_small_int_t i, ny, nz;
84350 	duk_uint32_t ty, tz;
84351 	duk_int64_t tmp;
84352 
84353 	DUK_ASSERT(duk__bi_is_valid(y));
84354 	DUK_ASSERT(duk__bi_is_valid(z));
84355 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
84356 	DUK_ASSERT(y->n >= z->n);
84357 
84358 	ny = y->n; nz = z->n;
84359 	tmp = 0;
84360 	for (i = 0; i < ny; i++) {
84361 		ty = y->v[i];
84362 		if (i < nz) {
84363 			tz = z->v[i];
84364 		} else {
84365 			tz = 0;
84366 		}
84367 		tmp = (duk_int64_t) ty - (duk_int64_t) tz + tmp;
84368 		x->v[i] = (duk_uint32_t) ((duk_uint64_t) tmp & 0xffffffffUL);
84369 		tmp = tmp >> 32;  /* 0 or -1 */
84370 	}
84371 	DUK_ASSERT(tmp == 0);
84372 
84373 	x->n = i;
84374 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
84375 	DUK_ASSERT(duk__bi_is_valid(x));
84376 }
84377 #else
84378 DUK_LOCAL void duk__bi_sub(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84379 	duk_small_int_t i, ny, nz;
84380 	duk_uint32_t tmp1, tmp2, borrow;
84381 
84382 	DUK_ASSERT(duk__bi_is_valid(y));
84383 	DUK_ASSERT(duk__bi_is_valid(z));
84384 	DUK_ASSERT(duk__bi_compare(y, z) >= 0);
84385 	DUK_ASSERT(y->n >= z->n);
84386 
84387 	ny = y->n; nz = z->n;
84388 	borrow = 0U;
84389 	for (i = 0; i < ny; i++) {
84390 		/* Borrow is detected based on wrapping which relies on exact 32-bit
84391 		 * types.
84392 		 */
84393 		tmp1 = y->v[i];
84394 		tmp2 = tmp1;
84395 		if (i < nz) {
84396 			tmp2 -= z->v[i];
84397 		}
84398 
84399 		/* Careful with borrow condition:
84400 		 *  - If borrow not subtracted: 0x12345678 - 0 - 0xffffffff = 0x12345679 (> 0x12345678)
84401 		 *  - If borrow subtracted:     0x12345678 - 1 - 0xffffffff = 0x12345678 (== 0x12345678)
84402 		 */
84403 		if (borrow) {
84404 			tmp2--;
84405 			borrow = (tmp2 >= tmp1 ? 1U : 0U);
84406 		} else {
84407 			borrow = (tmp2 > tmp1 ? 1U : 0U);
84408 		}
84409 
84410 		x->v[i] = tmp2;
84411 	}
84412 	DUK_ASSERT(borrow == 0U);
84413 
84414 	x->n = i;
84415 	duk__bi_normalize(x);  /* need to normalize, may even cancel to 0 */
84416 	DUK_ASSERT(duk__bi_is_valid(x));
84417 }
84418 #endif
84419 
84420 #if 0  /* unused */
84421 /* x <- y - z */
84422 DUK_LOCAL void duk__bi_sub_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84423 	duk__bigint tmp;
84424 
84425 	DUK_ASSERT(duk__bi_is_valid(y));
84426 
84427 	/* XXX: this could be optimized */
84428 	duk__bi_set_small(&tmp, z);
84429 	duk__bi_sub(x, y, &tmp);
84430 
84431 	DUK_ASSERT(duk__bi_is_valid(x));
84432 }
84433 #endif
84434 
84435 /* x <- x - y, use t as temp */
84436 DUK_LOCAL void duk__bi_sub_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84437 	duk__bi_sub(t, x, y);
84438 	duk__bi_copy(x, t);
84439 }
84440 
84441 /* x <- y * z */
84442 DUK_LOCAL void duk__bi_mul(duk__bigint *x, duk__bigint *y, duk__bigint *z) {
84443 	duk_small_int_t i, j, nx, nz;
84444 
84445 	DUK_ASSERT(duk__bi_is_valid(y));
84446 	DUK_ASSERT(duk__bi_is_valid(z));
84447 
84448 	nx = y->n + z->n;  /* max possible */
84449 	DUK_ASSERT(nx <= DUK__BI_MAX_PARTS);
84450 
84451 	if (nx == 0) {
84452 		/* Both inputs are zero; cases where only one is zero can go
84453 		 * through main algorithm.
84454 		 */
84455 		x->n = 0;
84456 		return;
84457 	}
84458 
84459 	duk_memzero((void *) x->v, (size_t) (sizeof(duk_uint32_t) * (size_t) nx));
84460 	x->n = nx;
84461 
84462 	nz = z->n;
84463 	for (i = 0; i < y->n; i++) {
84464 #if defined(DUK_USE_64BIT_OPS)
84465 		duk_uint64_t tmp = 0U;
84466 		for (j = 0; j < nz; j++) {
84467 			tmp += (duk_uint64_t) y->v[i] * (duk_uint64_t) z->v[j] + x->v[i+j];
84468 			x->v[i+j] = (duk_uint32_t) (tmp & 0xffffffffUL);
84469 			tmp = tmp >> 32;
84470 		}
84471 		if (tmp > 0) {
84472 			DUK_ASSERT(i + j < nx);
84473 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
84474 			DUK_ASSERT(x->v[i+j] == 0U);
84475 			x->v[i+j] = (duk_uint32_t) tmp;
84476 		}
84477 #else
84478 		/*
84479 		 *  Multiply + add + carry for 32-bit components using only 16x16->32
84480 		 *  multiplies and carry detection based on unsigned overflow.
84481 		 *
84482 		 *    1st mult, 32-bit: (A*2^16 + B)
84483 		 *    2nd mult, 32-bit: (C*2^16 + D)
84484 		 *    3rd add, 32-bit: E
84485 		 *    4th add, 32-bit: F
84486 		 *
84487 		 *      (AC*2^16 + B) * (C*2^16 + D) + E + F
84488 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + BD + E + F
84489 		 *    = AC*2^32 + (AD + BC)*2^16 + (BD + E + F)
84490 		 *    = AC*2^32 + AD*2^16 + BC*2^16 + (BD + E + F)
84491 		 */
84492 		duk_uint32_t a, b, c, d, e, f;
84493 		duk_uint32_t r, s, t;
84494 
84495 		a = y->v[i]; b = a & 0xffffUL; a = a >> 16;
84496 
84497 		f = 0;
84498 		for (j = 0; j < nz; j++) {
84499 			c = z->v[j]; d = c & 0xffffUL; c = c >> 16;
84500 			e = x->v[i+j];
84501 
84502 			/* build result as: (r << 32) + s: start with (BD + E + F) */
84503 			r = 0;
84504 			s = b * d;
84505 
84506 			/* add E */
84507 			t = s + e;
84508 			if (t < s) { r++; }  /* carry */
84509 			s = t;
84510 
84511 			/* add F */
84512 			t = s + f;
84513 			if (t < s) { r++; }  /* carry */
84514 			s = t;
84515 
84516 			/* add BC*2^16 */
84517 			t = b * c;
84518 			r += (t >> 16);
84519 			t = s + ((t & 0xffffUL) << 16);
84520 			if (t < s) { r++; }  /* carry */
84521 			s = t;
84522 
84523 			/* add AD*2^16 */
84524 			t = a * d;
84525 			r += (t >> 16);
84526 			t = s + ((t & 0xffffUL) << 16);
84527 			if (t < s) { r++; }  /* carry */
84528 			s = t;
84529 
84530 			/* add AC*2^32 */
84531 			t = a * c;
84532 			r += t;
84533 
84534 			DUK_DDD(DUK_DDDPRINT("ab=%08lx cd=%08lx ef=%08lx -> rs=%08lx %08lx",
84535 			                     (unsigned long) y->v[i], (unsigned long) z->v[j],
84536 			                     (unsigned long) x->v[i+j], (unsigned long) r,
84537 			                     (unsigned long) s));
84538 
84539 			x->v[i+j] = s;
84540 			f = r;
84541 		}
84542 		if (f > 0U) {
84543 			DUK_ASSERT(i + j < nx);
84544 			DUK_ASSERT(i + j < DUK__BI_MAX_PARTS);
84545 			DUK_ASSERT(x->v[i+j] == 0U);
84546 			x->v[i+j] = (duk_uint32_t) f;
84547 		}
84548 #endif  /* DUK_USE_64BIT_OPS */
84549 	}
84550 
84551 	duk__bi_normalize(x);
84552 	DUK_ASSERT(duk__bi_is_valid(x));
84553 }
84554 
84555 /* x <- y * z */
84556 DUK_LOCAL void duk__bi_mul_small(duk__bigint *x, duk__bigint *y, duk_uint32_t z) {
84557 	duk__bigint tmp;
84558 
84559 	DUK_ASSERT(duk__bi_is_valid(y));
84560 
84561 	/* XXX: this could be optimized */
84562 	duk__bi_set_small(&tmp, z);
84563 	duk__bi_mul(x, y, &tmp);
84564 
84565 	DUK_ASSERT(duk__bi_is_valid(x));
84566 }
84567 
84568 /* x <- x * y, use t as temp */
84569 DUK_LOCAL void duk__bi_mul_copy(duk__bigint *x, duk__bigint *y, duk__bigint *t) {
84570 	duk__bi_mul(t, x, y);
84571 	duk__bi_copy(x, t);
84572 }
84573 
84574 /* x <- x * y, use t as temp */
84575 DUK_LOCAL void duk__bi_mul_small_copy(duk__bigint *x, duk_uint32_t y, duk__bigint *t) {
84576 	duk__bi_mul_small(t, x, y);
84577 	duk__bi_copy(x, t);
84578 }
84579 
84580 DUK_LOCAL int duk__bi_is_even(duk__bigint *x) {
84581 	DUK_ASSERT(duk__bi_is_valid(x));
84582 	return (x->n == 0) || ((x->v[0] & 0x01) == 0);
84583 }
84584 
84585 DUK_LOCAL int duk__bi_is_zero(duk__bigint *x) {
84586 	DUK_ASSERT(duk__bi_is_valid(x));
84587 	return (x->n == 0);  /* this is the case for normalized numbers */
84588 }
84589 
84590 /* Bigint is 2^52.  Used to detect normalized IEEE double mantissa values
84591  * which are at the lowest edge (next floating point value downwards has
84592  * a different exponent).  The lowest mantissa has the form:
84593  *
84594  *     1000........000    (52 zeroes; only "hidden bit" is set)
84595  */
84596 DUK_LOCAL duk_small_int_t duk__bi_is_2to52(duk__bigint *x) {
84597 	DUK_ASSERT(duk__bi_is_valid(x));
84598 	return (duk_small_int_t)
84599 	        (x->n == 2) && (x->v[0] == 0U) && (x->v[1] == (1U << (52-32)));
84600 }
84601 
84602 /* x <- (1<<y) */
84603 DUK_LOCAL void duk__bi_twoexp(duk__bigint *x, duk_small_int_t y) {
84604 	duk_small_int_t n, r;
84605 
84606 	n = (y / 32) + 1;
84607 	DUK_ASSERT(n > 0);
84608 	r = y % 32;
84609 	duk_memzero((void *) x->v, sizeof(duk_uint32_t) * (size_t) n);
84610 	x->n = n;
84611 	x->v[n - 1] = (((duk_uint32_t) 1) << r);
84612 }
84613 
84614 /* x <- b^y; use t1 and t2 as temps */
84615 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) {
84616 	/* Fast path the binary case */
84617 
84618 	DUK_ASSERT(x != t1 && x != t2 && t1 != t2);  /* distinct bignums, easy mistake to make */
84619 	DUK_ASSERT(b >= 0);
84620 	DUK_ASSERT(y >= 0);
84621 
84622 	if (b == 2) {
84623 		duk__bi_twoexp(x, y);
84624 		return;
84625 	}
84626 
84627 	/* http://en.wikipedia.org/wiki/Exponentiation_by_squaring */
84628 
84629 	DUK_DDD(DUK_DDDPRINT("exp_small: b=%ld, y=%ld", (long) b, (long) y));
84630 
84631 	duk__bi_set_small(x, 1);
84632 	duk__bi_set_small(t1, (duk_uint32_t) b);
84633 	for (;;) {
84634 		/* Loop structure ensures that we don't compute t1^2 unnecessarily
84635 		 * on the final round, as that might create a bignum exceeding the
84636 		 * current DUK__BI_MAX_PARTS limit.
84637 		 */
84638 		if (y & 0x01) {
84639 			duk__bi_mul_copy(x, t1, t2);
84640 		}
84641 		y = y >> 1;
84642 		if (y == 0) {
84643 			break;
84644 		}
84645 		duk__bi_mul_copy(t1, t1, t2);
84646 	}
84647 
84648 	DUK__BI_PRINT("exp_small result", x);
84649 }
84650 
84651 /*
84652  *  A Dragon4 number-to-string variant, based on:
84653  *
84654  *    Guy L. Steele Jr., Jon L. White: "How to Print Floating-Point Numbers
84655  *    Accurately"
84656  *
84657  *    Robert G. Burger, R. Kent Dybvig: "Printing Floating-Point Numbers
84658  *    Quickly and Accurately"
84659  *
84660  *  The current algorithm is based on Figure 1 of the Burger-Dybvig paper,
84661  *  i.e. the base implementation without logarithm estimation speedups
84662  *  (these would increase code footprint considerably).  Fixed-format output
84663  *  does not follow the suggestions in the paper; instead, we generate an
84664  *  extra digit and round-with-carry.
84665  *
84666  *  The same algorithm is used for number parsing (with b=10 and B=2)
84667  *  by generating one extra digit and doing rounding manually.
84668  *
84669  *  See doc/number-conversion.rst for limitations.
84670  */
84671 
84672 /* Maximum number of digits generated. */
84673 #define DUK__MAX_OUTPUT_DIGITS          1040  /* (Number.MAX_VALUE).toString(2).length == 1024, + slack */
84674 
84675 /* Maximum number of characters in formatted value. */
84676 #define DUK__MAX_FORMATTED_LENGTH       1040  /* (-Number.MAX_VALUE).toString(2).length == 1025, + slack */
84677 
84678 /* Number and (minimum) size of bigints in the nc_ctx structure. */
84679 #define DUK__NUMCONV_CTX_NUM_BIGINTS    7
84680 #define DUK__NUMCONV_CTX_BIGINTS_SIZE   (sizeof(duk__bigint) * DUK__NUMCONV_CTX_NUM_BIGINTS)
84681 
84682 typedef struct {
84683 	/* Currently about 7*152 = 1064 bytes.  The space for these
84684 	 * duk__bigints is used also as a temporary buffer for generating
84685 	 * the final string.  This is a bit awkard; a union would be
84686 	 * more correct.
84687 	 */
84688 	duk__bigint f, r, s, mp, mm, t1, t2;
84689 
84690 	duk_small_int_t is_s2n;        /* if 1, doing a string-to-number; else doing a number-to-string */
84691 	duk_small_int_t is_fixed;      /* if 1, doing a fixed format output (not free format) */
84692 	duk_small_int_t req_digits;    /* requested number of output digits; 0 = free-format */
84693 	duk_small_int_t abs_pos;       /* digit position is absolute, not relative */
84694 	duk_small_int_t e;             /* exponent for 'f' */
84695 	duk_small_int_t b;             /* input radix */
84696 	duk_small_int_t B;             /* output radix */
84697 	duk_small_int_t k;             /* see algorithm */
84698 	duk_small_int_t low_ok;        /* see algorithm */
84699 	duk_small_int_t high_ok;       /* see algorithm */
84700 	duk_small_int_t unequal_gaps;  /* m+ != m- (very rarely) */
84701 
84702 	/* Buffer used for generated digits, values are in the range [0,B-1]. */
84703 	duk_uint8_t digits[DUK__MAX_OUTPUT_DIGITS];
84704 	duk_small_int_t count;  /* digit count */
84705 } duk__numconv_stringify_ctx;
84706 
84707 /* Note: computes with 'idx' in assertions, so caller beware.
84708  * 'idx' is preincremented, i.e. '1' on first call, because it
84709  * is more convenient for the caller.
84710  */
84711 #define DUK__DRAGON4_OUTPUT_PREINC(nc_ctx,preinc_idx,x)  do { \
84712 		DUK_ASSERT((preinc_idx) - 1 >= 0); \
84713 		DUK_ASSERT((preinc_idx) - 1 < DUK__MAX_OUTPUT_DIGITS); \
84714 		((nc_ctx)->digits[(preinc_idx) - 1]) = (duk_uint8_t) (x); \
84715 	} while (0)
84716 
84717 DUK_LOCAL duk_size_t duk__dragon4_format_uint32(duk_uint8_t *buf, duk_uint32_t x, duk_small_int_t radix) {
84718 	duk_uint8_t *p;
84719 	duk_size_t len;
84720 	duk_small_int_t dig;
84721 	duk_uint32_t t;
84722 
84723 	DUK_ASSERT(buf != NULL);
84724 	DUK_ASSERT(radix >= 2 && radix <= 36);
84725 
84726 	/* A 32-bit unsigned integer formats to at most 32 digits (the
84727 	 * worst case happens with radix == 2).  Output the digits backwards,
84728 	 * and use a memmove() to get them in the right place.
84729 	 */
84730 
84731 	p = buf + 32;
84732 	for (;;) {
84733 		t = x / (duk_uint32_t) radix;
84734 		dig = (duk_small_int_t) (x - t * (duk_uint32_t) radix);
84735 		x = t;
84736 
84737 		DUK_ASSERT(dig >= 0 && dig < 36);
84738 		*(--p) = DUK__DIGITCHAR(dig);
84739 
84740 		if (x == 0) {
84741 			break;
84742 		}
84743 	}
84744 	len = (duk_size_t) ((buf + 32) - p);
84745 
84746 	duk_memmove((void *) buf, (const void *) p, (size_t) len);
84747 
84748 	return len;
84749 }
84750 
84751 DUK_LOCAL void duk__dragon4_prepare(duk__numconv_stringify_ctx *nc_ctx) {
84752 	duk_small_int_t lowest_mantissa;
84753 
84754 #if 1
84755 	/* Assume IEEE round-to-even, so that shorter encoding can be used
84756 	 * when round-to-even would produce correct result.  By removing
84757 	 * this check (and having low_ok == high_ok == 0) the results would
84758 	 * still be accurate but in some cases longer than necessary.
84759 	 */
84760 	if (duk__bi_is_even(&nc_ctx->f)) {
84761 		DUK_DDD(DUK_DDDPRINT("f is even"));
84762 		nc_ctx->low_ok = 1;
84763 		nc_ctx->high_ok = 1;
84764 	} else {
84765 		DUK_DDD(DUK_DDDPRINT("f is odd"));
84766 		nc_ctx->low_ok = 0;
84767 		nc_ctx->high_ok = 0;
84768 	}
84769 #else
84770 	/* Note: not honoring round-to-even should work but now generates incorrect
84771 	 * results.  For instance, 1e23 serializes to "a000...", i.e. the first digit
84772 	 * equals the radix (10).  Scaling stops one step too early in this case.
84773 	 * Don't know why this is the case, but since this code path is unused, it
84774 	 * doesn't matter.
84775 	 */
84776 	nc_ctx->low_ok = 0;
84777 	nc_ctx->high_ok = 0;
84778 #endif
84779 
84780 	/* For string-to-number, pretend we never have the lowest mantissa as there
84781 	 * is no natural "precision" for inputs.  Having lowest_mantissa == 0, we'll
84782 	 * fall into the base cases for both e >= 0 and e < 0.
84783 	 */
84784 	if (nc_ctx->is_s2n) {
84785 		lowest_mantissa = 0;
84786 	} else {
84787 		lowest_mantissa = duk__bi_is_2to52(&nc_ctx->f);
84788 	}
84789 
84790 	nc_ctx->unequal_gaps = 0;
84791 	if (nc_ctx->e >= 0) {
84792 		/* exponent non-negative (and thus not minimum exponent) */
84793 
84794 		if (lowest_mantissa) {
84795 			/* (>= e 0) AND (= f (expt b (- p 1)))
84796 			 *
84797 			 * be <- (expt b e) == b^e
84798 			 * be1 <- (* be b) == (expt b (+ e 1)) == b^(e+1)
84799 			 * r <- (* f be1 2) == 2 * f * b^(e+1)    [if b==2 -> f * b^(e+2)]
84800 			 * s <- (* b 2)                           [if b==2 -> 4]
84801 			 * m+ <- be1 == b^(e+1)
84802 			 * m- <- be == b^e
84803 			 * k <- 0
84804 			 * B <- B
84805 			 * low_ok <- round
84806 			 * high_ok <- round
84807 			 */
84808 
84809 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
84810 			                     "lowest mantissa value for this exponent -> "
84811 			                     "unequal gaps"));
84812 
84813 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
84814 			duk__bi_mul_small(&nc_ctx->mp, &nc_ctx->mm, (duk_uint32_t) nc_ctx->b);           /* mp <- b^(e+1) */
84815 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
84816 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);              /* r <- (2 * f) * b^(e+1) */
84817 			duk__bi_set_small(&nc_ctx->s, (duk_uint32_t) (nc_ctx->b * 2));  /* s <- 2 * b */
84818 			nc_ctx->unequal_gaps = 1;
84819 		} else {
84820 			/* (>= e 0) AND (not (= f (expt b (- p 1))))
84821 			 *
84822 			 * be <- (expt b e) == b^e
84823 			 * r <- (* f be 2) == 2 * f * b^e    [if b==2 -> f * b^(e+1)]
84824 			 * s <- 2
84825 			 * m+ <- be == b^e
84826 			 * m- <- be == b^e
84827 			 * k <- 0
84828 			 * B <- B
84829 			 * low_ok <- round
84830 			 * high_ok <- round
84831 			 */
84832 
84833 			DUK_DDD(DUK_DDDPRINT("non-negative exponent (not smallest exponent); "
84834 			                     "not lowest mantissa for this exponent -> "
84835 			                     "equal gaps"));
84836 
84837 			duk__bi_exp_small(&nc_ctx->mm, nc_ctx->b, nc_ctx->e, &nc_ctx->t1, &nc_ctx->t2);  /* mm <- b^e */
84838 			duk__bi_copy(&nc_ctx->mp, &nc_ctx->mm);                /* mp <- b^e */
84839 			duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, 2);
84840 			duk__bi_mul(&nc_ctx->r, &nc_ctx->t1, &nc_ctx->mp);     /* r <- (2 * f) * b^e */
84841 			duk__bi_set_small(&nc_ctx->s, 2);                      /* s <- 2 */
84842 		}
84843 	} else {
84844 		/* When doing string-to-number, lowest_mantissa is always 0 so
84845 		 * the exponent check, while incorrect, won't matter.
84846 		 */
84847 		if (nc_ctx->e > DUK__IEEE_DOUBLE_EXP_MIN /*not minimum exponent*/ &&
84848 		    lowest_mantissa /* lowest mantissa for this exponent*/) {
84849 			/* r <- (* f b 2)                                [if b==2 -> (* f 4)]
84850 			 * s <- (* (expt b (- 1 e)) 2) == b^(1-e) * 2    [if b==2 -> b^(2-e)]
84851 			 * m+ <- b == 2
84852 			 * m- <- 1
84853 			 * k <- 0
84854 			 * B <- B
84855 			 * low_ok <- round
84856 			 * high_ok <- round
84857 			 */
84858 
84859 			DUK_DDD(DUK_DDDPRINT("negative exponent; not minimum exponent and "
84860 			                     "lowest mantissa for this exponent -> "
84861 			                     "unequal gaps"));
84862 
84863 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, (duk_uint32_t) (nc_ctx->b * 2));  /* r <- (2 * b) * f */
84864 			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 */
84865 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);             /* s <- b^(1-e) * 2 */
84866 			duk__bi_set_small(&nc_ctx->mp, 2);
84867 			duk__bi_set_small(&nc_ctx->mm, 1);
84868 			nc_ctx->unequal_gaps = 1;
84869 		} else {
84870 			/* r <- (* f 2)
84871 			 * s <- (* (expt b (- e)) 2) == b^(-e) * 2    [if b==2 -> b^(1-e)]
84872 			 * m+ <- 1
84873 			 * m- <- 1
84874 			 * k <- 0
84875 			 * B <- B
84876 			 * low_ok <- round
84877 			 * high_ok <- round
84878 			 */
84879 
84880 			DUK_DDD(DUK_DDDPRINT("negative exponent; minimum exponent or not "
84881 			                     "lowest mantissa for this exponent -> "
84882 			                     "equal gaps"));
84883 
84884 			duk__bi_mul_small(&nc_ctx->r, &nc_ctx->f, 2);            /* r <- 2 * f */
84885 			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 */
84886 			duk__bi_mul_small(&nc_ctx->s, &nc_ctx->t1, 2);           /* s <- b^(-e) * 2 */
84887 			duk__bi_set_small(&nc_ctx->mp, 1);
84888 			duk__bi_set_small(&nc_ctx->mm, 1);
84889 		}
84890 	}
84891 }
84892 
84893 DUK_LOCAL void duk__dragon4_scale(duk__numconv_stringify_ctx *nc_ctx) {
84894 	duk_small_int_t k = 0;
84895 
84896 	/* This is essentially the 'scale' algorithm, with recursion removed.
84897 	 * Note that 'k' is either correct immediately, or will move in one
84898 	 * direction in the loop.  There's no need to do the low/high checks
84899 	 * on every round (like the Scheme algorithm does).
84900 	 *
84901 	 * The scheme algorithm finds 'k' and updates 's' simultaneously,
84902 	 * while the logical algorithm finds 'k' with 's' having its initial
84903 	 * value, after which 's' is updated separately (see the Burger-Dybvig
84904 	 * paper, Section 3.1, steps 2 and 3).
84905 	 *
84906 	 * The case where m+ == m- (almost always) is optimized for, because
84907 	 * it reduces the bigint operations considerably and almost always
84908 	 * applies.  The scale loop only needs to work with m+, so this works.
84909 	 */
84910 
84911 	/* XXX: this algorithm could be optimized quite a lot by using e.g.
84912 	 * a logarithm based estimator for 'k' and performing B^n multiplication
84913 	 * using a lookup table or using some bit-representation based exp
84914 	 * algorithm.  Currently we just loop, with significant performance
84915 	 * impact for very large and very small numbers.
84916 	 */
84917 
84918 	DUK_DDD(DUK_DDDPRINT("scale: B=%ld, low_ok=%ld, high_ok=%ld",
84919 	                     (long) nc_ctx->B, (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
84920 	DUK__BI_PRINT("r(init)", &nc_ctx->r);
84921 	DUK__BI_PRINT("s(init)", &nc_ctx->s);
84922 	DUK__BI_PRINT("mp(init)", &nc_ctx->mp);
84923 	DUK__BI_PRINT("mm(init)", &nc_ctx->mm);
84924 
84925 	for (;;) {
84926 		DUK_DDD(DUK_DDDPRINT("scale loop (inc k), k=%ld", (long) k));
84927 		DUK__BI_PRINT("r", &nc_ctx->r);
84928 		DUK__BI_PRINT("s", &nc_ctx->s);
84929 		DUK__BI_PRINT("m+", &nc_ctx->mp);
84930 		DUK__BI_PRINT("m-", &nc_ctx->mm);
84931 
84932 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
84933 		if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1)) {
84934 			DUK_DDD(DUK_DDDPRINT("k is too low"));
84935 			/* r <- r
84936 			 * s <- (* s B)
84937 			 * m+ <- m+
84938 			 * m- <- m-
84939 			 * k <- (+ k 1)
84940 			 */
84941 
84942 			duk__bi_mul_small_copy(&nc_ctx->s, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84943 			k++;
84944 		} else {
84945 			break;
84946 		}
84947 	}
84948 
84949 	/* k > 0 -> k was too low, and cannot be too high */
84950 	if (k > 0) {
84951 		goto skip_dec_k;
84952 	}
84953 
84954 	for (;;) {
84955 		DUK_DDD(DUK_DDDPRINT("scale loop (dec k), k=%ld", (long) k));
84956 		DUK__BI_PRINT("r", &nc_ctx->r);
84957 		DUK__BI_PRINT("s", &nc_ctx->s);
84958 		DUK__BI_PRINT("m+", &nc_ctx->mp);
84959 		DUK__BI_PRINT("m-", &nc_ctx->mm);
84960 
84961 		duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 = (+ r m+) */
84962 		duk__bi_mul_small(&nc_ctx->t2, &nc_ctx->t1, (duk_uint32_t) nc_ctx->B);   /* t2 = (* (+ r m+) B) */
84963 		if (duk__bi_compare(&nc_ctx->t2, &nc_ctx->s) <= (nc_ctx->high_ok ? -1 : 0)) {
84964 			DUK_DDD(DUK_DDDPRINT("k is too high"));
84965 			/* r <- (* r B)
84966 			 * s <- s
84967 			 * m+ <- (* m+ B)
84968 			 * m- <- (* m- B)
84969 			 * k <- (- k 1)
84970 			 */
84971 			duk__bi_mul_small_copy(&nc_ctx->r, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84972 			duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84973 			if (nc_ctx->unequal_gaps) {
84974 				DUK_DDD(DUK_DDDPRINT("m+ != m- -> need to update m- too"));
84975 				duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t1);
84976 			}
84977 			k--;
84978 		} else {
84979 			break;
84980 		}
84981 	}
84982 
84983  skip_dec_k:
84984 
84985 	if (!nc_ctx->unequal_gaps) {
84986 		DUK_DDD(DUK_DDDPRINT("equal gaps, copy m- from m+"));
84987 		duk__bi_copy(&nc_ctx->mm, &nc_ctx->mp);  /* mm <- mp */
84988 	}
84989 	nc_ctx->k = k;
84990 
84991 	DUK_DDD(DUK_DDDPRINT("final k: %ld", (long) k));
84992 	DUK__BI_PRINT("r(final)", &nc_ctx->r);
84993 	DUK__BI_PRINT("s(final)", &nc_ctx->s);
84994 	DUK__BI_PRINT("mp(final)", &nc_ctx->mp);
84995 	DUK__BI_PRINT("mm(final)", &nc_ctx->mm);
84996 }
84997 
84998 DUK_LOCAL void duk__dragon4_generate(duk__numconv_stringify_ctx *nc_ctx) {
84999 	duk_small_int_t tc1, tc2;    /* terminating conditions */
85000 	duk_small_int_t d;           /* current digit */
85001 	duk_small_int_t count = 0;   /* digit count */
85002 
85003 	/*
85004 	 *  Digit generation loop.
85005 	 *
85006 	 *  Different termination conditions:
85007 	 *
85008 	 *    1. Free format output.  Terminate when shortest accurate
85009 	 *       representation found.
85010 	 *
85011 	 *    2. Fixed format output, with specific number of digits.
85012 	 *       Ignore termination conditions, terminate when digits
85013 	 *       generated.  Caller requests an extra digit and rounds.
85014 	 *
85015 	 *    3. Fixed format output, with a specific absolute cut-off
85016 	 *       position (e.g. 10 digits after decimal point).  Note
85017 	 *       that we always generate at least one digit, even if
85018 	 *       the digit is below the cut-off point already.
85019 	 */
85020 
85021 	for (;;) {
85022 		DUK_DDD(DUK_DDDPRINT("generate loop, count=%ld, k=%ld, B=%ld, low_ok=%ld, high_ok=%ld",
85023 		                     (long) count, (long) nc_ctx->k, (long) nc_ctx->B,
85024 		                     (long) nc_ctx->low_ok, (long) nc_ctx->high_ok));
85025 		DUK__BI_PRINT("r", &nc_ctx->r);
85026 		DUK__BI_PRINT("s", &nc_ctx->s);
85027 		DUK__BI_PRINT("m+", &nc_ctx->mp);
85028 		DUK__BI_PRINT("m-", &nc_ctx->mm);
85029 
85030 		/* (quotient-remainder (* r B) s) using a dummy subtraction loop */
85031 		duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, (duk_uint32_t) nc_ctx->B);       /* t1 <- (* r B) */
85032 		d = 0;
85033 		for (;;) {
85034 			if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {
85035 				break;
85036 			}
85037 			duk__bi_sub_copy(&nc_ctx->t1, &nc_ctx->s, &nc_ctx->t2);  /* t1 <- t1 - s */
85038 			d++;
85039 		}
85040 		duk__bi_copy(&nc_ctx->r, &nc_ctx->t1);  /* r <- (remainder (* r B) s) */
85041 		                                        /* d <- (quotient (* r B) s)   (in range 0...B-1) */
85042 		DUK_DDD(DUK_DDDPRINT("-> d(quot)=%ld", (long) d));
85043 		DUK__BI_PRINT("r(rem)", &nc_ctx->r);
85044 
85045 		duk__bi_mul_small_copy(&nc_ctx->mp, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m+ <- (* m+ B) */
85046 		duk__bi_mul_small_copy(&nc_ctx->mm, (duk_uint32_t) nc_ctx->B, &nc_ctx->t2); /* m- <- (* m- B) */
85047 		DUK__BI_PRINT("mp(upd)", &nc_ctx->mp);
85048 		DUK__BI_PRINT("mm(upd)", &nc_ctx->mm);
85049 
85050 		/* Terminating conditions.  For fixed width output, we just ignore the
85051 		 * terminating conditions (and pretend that tc1 == tc2 == false).  The
85052 		 * the current shortcut for fixed-format output is to generate a few
85053 		 * extra digits and use rounding (with carry) to finish the output.
85054 		 */
85055 
85056 		if (nc_ctx->is_fixed == 0) {
85057 			/* free-form */
85058 			tc1 = (duk__bi_compare(&nc_ctx->r, &nc_ctx->mm) <= (nc_ctx->low_ok ? 0 : -1));
85059 
85060 			duk__bi_add(&nc_ctx->t1, &nc_ctx->r, &nc_ctx->mp);  /* t1 <- (+ r m+) */
85061 			tc2 = (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) >= (nc_ctx->high_ok ? 0 : 1));
85062 
85063 			DUK_DDD(DUK_DDDPRINT("tc1=%ld, tc2=%ld", (long) tc1, (long) tc2));
85064 		} else {
85065 			/* fixed-format */
85066 			tc1 = 0;
85067 			tc2 = 0;
85068 		}
85069 
85070 		/* Count is incremented before DUK__DRAGON4_OUTPUT_PREINC() call
85071 		 * on purpose, which is taken into account by the macro.
85072 		 */
85073 		count++;
85074 
85075 		if (tc1) {
85076 			if (tc2) {
85077 				/* tc1 = true, tc2 = true */
85078 				duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->r, 2);
85079 				if (duk__bi_compare(&nc_ctx->t1, &nc_ctx->s) < 0) {  /* (< (* r 2) s) */
85080 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r > s: output d --> %ld (k=%ld)",
85081 					                     (long) d, (long) nc_ctx->k));
85082 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85083 				} else {
85084 					DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=true, 2r <= s: output d+1 --> %ld (k=%ld)",
85085 					                     (long) (d + 1), (long) nc_ctx->k));
85086 					DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85087 				}
85088 				break;
85089 			} else {
85090 				/* tc1 = true, tc2 = false */
85091 				DUK_DDD(DUK_DDDPRINT("tc1=true, tc2=false: output d --> %ld (k=%ld)",
85092 				                     (long) d, (long) nc_ctx->k));
85093 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85094 				break;
85095 			}
85096 		} else {
85097 			if (tc2) {
85098 				/* tc1 = false, tc2 = true */
85099 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=true: output d+1 --> %ld (k=%ld)",
85100 				                     (long) (d + 1), (long) nc_ctx->k));
85101 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d + 1);
85102 				break;
85103 			} else {
85104 				/* tc1 = false, tc2 = false */
85105 				DUK_DDD(DUK_DDDPRINT("tc1=false, tc2=false: output d --> %ld (k=%ld)",
85106 				                     (long) d, (long) nc_ctx->k));
85107 				DUK__DRAGON4_OUTPUT_PREINC(nc_ctx, count, d);
85108 
85109 				/* r <- r    (updated above: r <- (remainder (* r B) s)
85110 				 * s <- s
85111 				 * m+ <- m+  (updated above: m+ <- (* m+ B)
85112 				 * m- <- m-  (updated above: m- <- (* m- B)
85113 				 * B, low_ok, high_ok are fixed
85114 				 */
85115 
85116 				/* fall through and continue for-loop */
85117 			}
85118 		}
85119 
85120 		/* fixed-format termination conditions */
85121 		if (nc_ctx->is_fixed) {
85122 			if (nc_ctx->abs_pos) {
85123 				int pos = nc_ctx->k - count + 1;  /* count is already incremented, take into account */
85124 				DUK_DDD(DUK_DDDPRINT("fixed format, absolute: abs pos=%ld, k=%ld, count=%ld, req=%ld",
85125 				                     (long) pos, (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85126 				if (pos <= nc_ctx->req_digits) {
85127 					DUK_DDD(DUK_DDDPRINT("digit position reached req_digits, end generate loop"));
85128 					break;
85129 				}
85130 			} else {
85131 				DUK_DDD(DUK_DDDPRINT("fixed format, relative: k=%ld, count=%ld, req=%ld",
85132 				                     (long) nc_ctx->k, (long) count, (long) nc_ctx->req_digits));
85133 				if (count >= nc_ctx->req_digits) {
85134 					DUK_DDD(DUK_DDDPRINT("digit count reached req_digits, end generate loop"));
85135 					break;
85136 				}
85137 			}
85138 		}
85139 	}  /* for */
85140 
85141 	nc_ctx->count = count;
85142 
85143 	DUK_DDD(DUK_DDDPRINT("generate finished"));
85144 
85145 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
85146 	{
85147 		duk_uint8_t buf[2048];
85148 		duk_small_int_t i, t;
85149 		duk_memzero(buf, sizeof(buf));
85150 		for (i = 0; i < nc_ctx->count; i++) {
85151 			t = nc_ctx->digits[i];
85152 			if (t < 0 || t > 36) {
85153 				buf[i] = (duk_uint8_t) '?';
85154 			} else {
85155 				buf[i] = (duk_uint8_t) DUK__DIGITCHAR(t);
85156 			}
85157 		}
85158 		DUK_DDD(DUK_DDDPRINT("-> generated digits; k=%ld, digits='%s'",
85159 		                     (long) nc_ctx->k, (const char *) buf));
85160 	}
85161 #endif
85162 }
85163 
85164 /* Round up digits to a given position.  If position is out-of-bounds,
85165  * does nothing.  If carry propagates over the first digit, a '1' is
85166  * prepended to digits and 'k' will be updated.  Return value indicates
85167  * whether carry propagated over the first digit.
85168  *
85169  * Note that nc_ctx->count is NOT updated based on the rounding position
85170  * (it is updated only if carry overflows over the first digit and an
85171  * extra digit is prepended).
85172  */
85173 DUK_LOCAL duk_small_int_t duk__dragon4_fixed_format_round(duk__numconv_stringify_ctx *nc_ctx, duk_small_int_t round_idx) {
85174 	duk_small_int_t t;
85175 	duk_uint8_t *p;
85176 	duk_uint8_t roundup_limit;
85177 	duk_small_int_t ret = 0;
85178 
85179 	/*
85180 	 *  round_idx points to the digit which is considered for rounding; the
85181 	 *  digit to its left is the final digit of the rounded value.  If round_idx
85182 	 *  is zero, rounding will be performed; the result will either be an empty
85183 	 *  rounded value or if carry happens a '1' digit is generated.
85184 	 */
85185 
85186 	if (round_idx >= nc_ctx->count) {
85187 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld >= %ld (count)) -> no rounding",
85188 		                     (long) round_idx, (long) nc_ctx->count));
85189 		return 0;
85190 	} else if (round_idx < 0) {
85191 		DUK_DDD(DUK_DDDPRINT("round_idx out of bounds (%ld < 0) -> no rounding",
85192 		                     (long) round_idx));
85193 		return 0;
85194 	}
85195 
85196 	/*
85197 	 *  Round-up limit.
85198 	 *
85199 	 *  For even values, divides evenly, e.g. 10 -> roundup_limit=5.
85200 	 *
85201 	 *  For odd values, rounds up, e.g. 3 -> roundup_limit=2.
85202 	 *  If radix is 3, 0/3 -> down, 1/3 -> down, 2/3 -> up.
85203 	 */
85204 	roundup_limit = (duk_uint8_t) ((nc_ctx->B + 1) / 2);
85205 
85206 	p = &nc_ctx->digits[round_idx];
85207 	if (*p >= roundup_limit) {
85208 		DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry required"));
85209 		/* carry */
85210 		for (;;) {
85211 			*p = 0;
85212 			if (p == &nc_ctx->digits[0]) {
85213 				DUK_DDD(DUK_DDDPRINT("carry propagated to first digit -> special case handling"));
85214 				duk_memmove((void *) (&nc_ctx->digits[1]),
85215 				            (const void *) (&nc_ctx->digits[0]),
85216 				            (size_t) (sizeof(char) * (size_t) nc_ctx->count));
85217 				nc_ctx->digits[0] = 1;  /* don't increase 'count' */
85218 				nc_ctx->k++;  /* position of highest digit changed */
85219 				nc_ctx->count++;  /* number of digits changed */
85220 				ret = 1;
85221 				break;
85222 			}
85223 
85224 			DUK_DDD(DUK_DDDPRINT("fixed-format rounding carry: B=%ld, roundup_limit=%ld, p=%p, digits=%p",
85225 			                     (long) nc_ctx->B, (long) roundup_limit, (void *) p, (void *) nc_ctx->digits));
85226 			p--;
85227 			t = *p;
85228 			DUK_DDD(DUK_DDDPRINT("digit before carry: %ld", (long) t));
85229 			if (++t < nc_ctx->B) {
85230 				DUK_DDD(DUK_DDDPRINT("rounding carry terminated"));
85231 				*p = (duk_uint8_t) t;
85232 				break;
85233 			}
85234 
85235 			DUK_DDD(DUK_DDDPRINT("wraps, carry to next digit"));
85236 		}
85237 	}
85238 
85239 	return ret;
85240 }
85241 
85242 #define DUK__NO_EXP  (65536)  /* arbitrary marker, outside valid exp range */
85243 
85244 DUK_LOCAL void duk__dragon4_convert_and_push(duk__numconv_stringify_ctx *nc_ctx,
85245                                              duk_hthread *thr,
85246                                              duk_small_int_t radix,
85247                                              duk_small_int_t digits,
85248                                              duk_small_uint_t flags,
85249                                              duk_small_int_t neg) {
85250 	duk_small_int_t k;
85251 	duk_small_int_t pos, pos_end;
85252 	duk_small_int_t expt;
85253 	duk_small_int_t dig;
85254 	duk_uint8_t *q;
85255 	duk_uint8_t *buf;
85256 
85257 	/*
85258 	 *  The string conversion here incorporates all the necessary ECMAScript
85259 	 *  semantics without attempting to be generic.  nc_ctx->digits contains
85260 	 *  nc_ctx->count digits (>= 1), with the topmost digit's 'position'
85261 	 *  indicated by nc_ctx->k as follows:
85262 	 *
85263 	 *    digits="123" count=3 k=0   -->   0.123
85264 	 *    digits="123" count=3 k=1   -->   1.23
85265 	 *    digits="123" count=3 k=5   -->   12300
85266 	 *    digits="123" count=3 k=-1  -->   0.0123
85267 	 *
85268 	 *  Note that the identifier names used for format selection are different
85269 	 *  in Burger-Dybvig paper and ECMAScript specification (quite confusingly
85270 	 *  so, because e.g. 'k' has a totally different meaning in each).  See
85271 	 *  documentation for discussion.
85272 	 *
85273 	 *  ECMAScript doesn't specify any specific behavior for format selection
85274 	 *  (e.g. when to use exponent notation) for non-base-10 numbers.
85275 	 *
85276 	 *  The bigint space in the context is reused for string output, as there
85277 	 *  is more than enough space for that (>1kB at the moment), and we avoid
85278 	 *  allocating even more stack.
85279 	 */
85280 
85281 	DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= DUK__MAX_FORMATTED_LENGTH);
85282 	DUK_ASSERT(nc_ctx->count >= 1);
85283 
85284 	k = nc_ctx->k;
85285 	buf = (duk_uint8_t *) &nc_ctx->f;  /* XXX: union would be more correct */
85286 	q = buf;
85287 
85288 	/* Exponent handling: if exponent format is used, record exponent value and
85289 	 * fake k such that one leading digit is generated (e.g. digits=123 -> "1.23").
85290 	 *
85291 	 * toFixed() prevents exponent use; otherwise apply a set of criteria to
85292 	 * match the other API calls (toString(), toPrecision, etc).
85293 	 */
85294 
85295 	expt = DUK__NO_EXP;
85296 	if (!nc_ctx->abs_pos /* toFixed() */) {
85297 		if ((flags & DUK_N2S_FLAG_FORCE_EXP) ||             /* exponential notation forced */
85298 		    ((flags & DUK_N2S_FLAG_NO_ZERO_PAD) &&          /* fixed precision and zero padding would be required */
85299 	             (k - digits >= 1)) ||                          /* (e.g. k=3, digits=2 -> "12X") */
85300 		    ((k > 21 || k <= -6) && (radix == 10))) {       /* toString() conditions */
85301 			DUK_DDD(DUK_DDDPRINT("use exponential notation: k=%ld -> expt=%ld",
85302 			                     (long) k, (long) (k - 1)));
85303 			expt = k - 1;  /* e.g. 12.3 -> digits="123" k=2 -> 1.23e1 */
85304 			k = 1;  /* generate mantissa with a single leading whole number digit */
85305 		}
85306 	}
85307 
85308 	if (neg) {
85309 		*q++ = '-';
85310 	}
85311 
85312 	/* Start position (inclusive) and end position (exclusive) */
85313 	pos = (k >= 1 ? k : 1);
85314 	if (nc_ctx->is_fixed) {
85315 		if (nc_ctx->abs_pos) {
85316 			/* toFixed() */
85317 			pos_end = -digits;
85318 		} else {
85319 			pos_end = k - digits;
85320 		}
85321 	} else {
85322 		pos_end = k - nc_ctx->count;
85323 	}
85324 	if (pos_end > 0) {
85325 		pos_end = 0;
85326 	}
85327 
85328 	DUK_DDD(DUK_DDDPRINT("expt=%ld, k=%ld, count=%ld, pos=%ld, pos_end=%ld, is_fixed=%ld, "
85329 	                     "digits=%ld, abs_pos=%ld",
85330 	                     (long) expt, (long) k, (long) nc_ctx->count, (long) pos, (long) pos_end,
85331 	                     (long) nc_ctx->is_fixed, (long) digits, (long) nc_ctx->abs_pos));
85332 
85333 	/* Digit generation */
85334 	while (pos > pos_end) {
85335 		DUK_DDD(DUK_DDDPRINT("digit generation: pos=%ld, pos_end=%ld",
85336 		                     (long) pos, (long) pos_end));
85337 		if (pos == 0) {
85338 			*q++ = (duk_uint8_t) '.';
85339 		}
85340 		if (pos > k) {
85341 			*q++ = (duk_uint8_t) '0';
85342 		} else if (pos <= k - nc_ctx->count) {
85343 			*q++ = (duk_uint8_t) '0';
85344 		} else {
85345 			dig = nc_ctx->digits[k - pos];
85346 			DUK_ASSERT(dig >= 0 && dig < nc_ctx->B);
85347 			*q++ = (duk_uint8_t) DUK__DIGITCHAR(dig);
85348 		}
85349 
85350 		pos--;
85351 	}
85352 	DUK_ASSERT(pos <= 1);
85353 
85354 	/* Exponent */
85355 	if (expt != DUK__NO_EXP) {
85356 		/*
85357 		 *  Exponent notation for non-base-10 numbers isn't specified in ECMAScript
85358 		 *  specification, as it never explicitly turns up: non-decimal numbers can
85359 		 *  only be formatted with Number.prototype.toString([radix]) and for that,
85360 		 *  behavior is not explicitly specified.
85361 		 *
85362 		 *  Logical choices include formatting the exponent as decimal (e.g. binary
85363 		 *  100000 as 1e+5) or in current radix (e.g. binary 100000 as 1e+101).
85364 		 *  The Dragon4 algorithm (in the original paper) prints the exponent value
85365 		 *  in the target radix B.  However, for radix values 15 and above, the
85366 		 *  exponent separator 'e' is no longer easily parseable.  Consider, for
85367 		 *  instance, the number "1.faecee+1c".
85368 		 */
85369 
85370 		duk_size_t len;
85371 		char expt_sign;
85372 
85373 		*q++ = 'e';
85374 		if (expt >= 0) {
85375 			expt_sign = '+';
85376 		} else {
85377 			expt_sign = '-';
85378 			expt = -expt;
85379 		}
85380 		*q++ = (duk_uint8_t) expt_sign;
85381 		len = duk__dragon4_format_uint32(q, (duk_uint32_t) expt, radix);
85382 		q += len;
85383 	}
85384 
85385 	duk_push_lstring(thr, (const char *) buf, (size_t) (q - buf));
85386 }
85387 
85388 /*
85389  *  Conversion helpers
85390  */
85391 
85392 DUK_LOCAL void duk__dragon4_double_to_ctx(duk__numconv_stringify_ctx *nc_ctx, duk_double_t x) {
85393 	duk_double_union u;
85394 	duk_uint32_t tmp;
85395 	duk_small_int_t expt;
85396 
85397 	/*
85398 	 *    seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff
85399 	 *       A        B        C        D        E        F        G        H
85400 	 *
85401 	 *    s       sign bit
85402 	 *    eee...  exponent field
85403 	 *    fff...  fraction
85404 	 *
85405 	 *    ieee value = 1.ffff... * 2^(e - 1023)  (normal)
85406 	 *               = 0.ffff... * 2^(-1022)     (denormal)
85407 	 *
85408 	 *    algorithm v = f * b^e
85409 	 */
85410 
85411 	DUK_DBLUNION_SET_DOUBLE(&u, x);
85412 
85413 	nc_ctx->f.n = 2;
85414 
85415 	tmp = DUK_DBLUNION_GET_LOW32(&u);
85416 	nc_ctx->f.v[0] = tmp;
85417 	tmp = DUK_DBLUNION_GET_HIGH32(&u);
85418 	nc_ctx->f.v[1] = tmp & 0x000fffffUL;
85419 	expt = (duk_small_int_t) ((tmp >> 20) & 0x07ffUL);
85420 
85421 	if (expt == 0) {
85422 		/* denormal */
85423 		expt = DUK__IEEE_DOUBLE_EXP_MIN - 52;
85424 		duk__bi_normalize(&nc_ctx->f);
85425 	} else {
85426 		/* normal: implicit leading 1-bit */
85427 		nc_ctx->f.v[1] |= 0x00100000UL;
85428 		expt = expt - DUK__IEEE_DOUBLE_EXP_BIAS - 52;
85429 		DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));  /* true, because v[1] has at least one bit set */
85430 	}
85431 
85432 	DUK_ASSERT(duk__bi_is_valid(&nc_ctx->f));
85433 
85434 	nc_ctx->e = expt;
85435 }
85436 
85437 DUK_LOCAL void duk__dragon4_ctx_to_double(duk__numconv_stringify_ctx *nc_ctx, duk_double_t *x) {
85438 	duk_double_union u;
85439 	duk_small_int_t expt;
85440 	duk_small_int_t i;
85441 	duk_small_int_t bitstart;
85442 	duk_small_int_t bitround;
85443 	duk_small_int_t bitidx;
85444 	duk_small_int_t skip_round;
85445 	duk_uint32_t t, v;
85446 
85447 	DUK_ASSERT(nc_ctx->count == 53 + 1);
85448 
85449 	/* Sometimes this assert is not true right now; it will be true after
85450 	 * rounding.  See: test-bug-numconv-mantissa-assert.js.
85451 	 */
85452 	DUK_ASSERT_DISABLE(nc_ctx->digits[0] == 1);  /* zero handled by caller */
85453 
85454 	/* Should not be required because the code below always sets both high
85455 	 * and low parts, but at least gcc-4.4.5 fails to deduce this correctly
85456 	 * (perhaps because the low part is set (seemingly) conditionally in a
85457 	 * loop), so this is here to avoid the bogus warning.
85458 	 */
85459 	duk_memzero((void *) &u, sizeof(u));
85460 
85461 	/*
85462 	 *  Figure out how generated digits match up with the mantissa,
85463 	 *  and then perform rounding.  If mantissa overflows, need to
85464 	 *  recompute the exponent (it is bumped and may overflow to
85465 	 *  infinity).
85466 	 *
85467 	 *  For normal numbers the leading '1' is hidden and ignored,
85468 	 *  and the last bit is used for rounding:
85469 	 *
85470 	 *                          rounding pt
85471 	 *       <--------52------->|
85472 	 *     1 x x x x ... x x x x|y  ==>  x x x x ... x x x x
85473 	 *
85474 	 *  For denormals, the leading '1' is included in the number,
85475 	 *  and the rounding point is different:
85476 	 *
85477 	 *                      rounding pt
85478 	 *     <--52 or less--->|
85479 	 *     1 x x x x ... x x|x x y  ==>  0 0 ... 1 x x ... x x
85480 	 *
85481 	 *  The largest denormals will have a mantissa beginning with
85482 	 *  a '1' (the explicit leading bit); smaller denormals will
85483 	 *  have leading zero bits.
85484 	 *
85485 	 *  If the exponent would become too high, the result becomes
85486 	 *  Infinity.  If the exponent is so small that the entire
85487 	 *  mantissa becomes zero, the result becomes zero.
85488 	 *
85489 	 *  Note: the Dragon4 'k' is off-by-one with respect to the IEEE
85490 	 *  exponent.  For instance, k==0 indicates that the leading '1'
85491 	 *  digit is at the first binary fraction position (0.1xxx...);
85492 	 *  the corresponding IEEE exponent would be -1.
85493 	 */
85494 
85495 	skip_round = 0;
85496 
85497  recheck_exp:
85498 
85499 	expt = nc_ctx->k - 1;   /* IEEE exp without bias */
85500 	if (expt > 1023) {
85501 		/* Infinity */
85502 		bitstart = -255;  /* needed for inf: causes mantissa to become zero,
85503 		                   * and rounding to be skipped.
85504 		                   */
85505 		expt = 2047;
85506 	} else if (expt >= -1022) {
85507 		/* normal */
85508 		bitstart = 1;  /* skip leading digit */
85509 		expt += DUK__IEEE_DOUBLE_EXP_BIAS;
85510 		DUK_ASSERT(expt >= 1 && expt <= 2046);
85511 	} else {
85512 		/* denormal or zero */
85513 		bitstart = 1023 + expt;  /* expt==-1023 -> bitstart=0 (leading 1);
85514 		                          * expt==-1024 -> bitstart=-1 (one left of leading 1), etc
85515 		                          */
85516 		expt = 0;
85517 	}
85518 	bitround = bitstart + 52;
85519 
85520 	DUK_DDD(DUK_DDDPRINT("ieee expt=%ld, bitstart=%ld, bitround=%ld",
85521 	                     (long) expt, (long) bitstart, (long) bitround));
85522 
85523 	if (!skip_round) {
85524 		if (duk__dragon4_fixed_format_round(nc_ctx, bitround)) {
85525 			/* Corner case: see test-numconv-parse-mant-carry.js.  We could
85526 			 * just bump the exponent and update bitstart, but it's more robust
85527 			 * to recompute (but avoid rounding twice).
85528 			 */
85529 			DUK_DDD(DUK_DDDPRINT("rounding caused exponent to be bumped, recheck exponent"));
85530 			skip_round = 1;
85531 			goto recheck_exp;
85532 		}
85533 	}
85534 
85535 	/*
85536 	 *  Create mantissa
85537 	 */
85538 
85539 	t = 0;
85540 	for (i = 0; i < 52; i++) {
85541 		bitidx = bitstart + 52 - 1 - i;
85542 		if (bitidx >= nc_ctx->count) {
85543 			v = 0;
85544 		} else if (bitidx < 0) {
85545 			v = 0;
85546 		} else {
85547 			v = nc_ctx->digits[bitidx];
85548 		}
85549 		DUK_ASSERT(v == 0 || v == 1);
85550 		t += v << (i % 32);
85551 		if (i == 31) {
85552 			/* low 32 bits is complete */
85553 			DUK_DBLUNION_SET_LOW32(&u, t);
85554 			t = 0;
85555 		}
85556 	}
85557 	/* t has high mantissa */
85558 
85559 	DUK_DDD(DUK_DDDPRINT("mantissa is complete: %08lx %08lx",
85560 	                     (unsigned long) t,
85561 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
85562 
85563 	DUK_ASSERT(expt >= 0 && expt <= 0x7ffL);
85564 	t += ((duk_uint32_t) expt) << 20;
85565 #if 0  /* caller handles sign change */
85566 	if (negative) {
85567 		t |= 0x80000000U;
85568 	}
85569 #endif
85570 	DUK_DBLUNION_SET_HIGH32(&u, t);
85571 
85572 	DUK_DDD(DUK_DDDPRINT("number is complete: %08lx %08lx",
85573 	                     (unsigned long) DUK_DBLUNION_GET_HIGH32(&u),
85574 	                     (unsigned long) DUK_DBLUNION_GET_LOW32(&u)));
85575 
85576 	*x = DUK_DBLUNION_GET_DOUBLE(&u);
85577 }
85578 
85579 /*
85580  *  Exposed number-to-string API
85581  *
85582  *  Input: [ number ]
85583  *  Output: [ string ]
85584  */
85585 
85586 DUK_INTERNAL void duk_numconv_stringify(duk_hthread *thr, duk_small_int_t radix, duk_small_int_t digits, duk_small_uint_t flags) {
85587 	duk_double_t x;
85588 	duk_small_int_t c;
85589 	duk_small_int_t neg;
85590 	duk_uint32_t uval;
85591 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
85592 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
85593 
85594 	x = (duk_double_t) duk_require_number(thr, -1);
85595 	duk_pop(thr);
85596 
85597 	/*
85598 	 *  Handle special cases (NaN, infinity, zero).
85599 	 */
85600 
85601 	c = (duk_small_int_t) DUK_FPCLASSIFY(x);
85602 	if (DUK_SIGNBIT((double) x)) {
85603 		x = -x;
85604 		neg = 1;
85605 	} else {
85606 		neg = 0;
85607 	}
85608 
85609 	/* NaN sign bit is platform specific with unpacked, un-normalized NaNs */
85610 	DUK_ASSERT(c == DUK_FP_NAN || DUK_SIGNBIT((double) x) == 0);
85611 
85612 	if (c == DUK_FP_NAN) {
85613 		duk_push_hstring_stridx(thr, DUK_STRIDX_NAN);
85614 		return;
85615 	} else if (c == DUK_FP_INFINITE) {
85616 		if (neg) {
85617 			/* -Infinity */
85618 			duk_push_hstring_stridx(thr, DUK_STRIDX_MINUS_INFINITY);
85619 		} else {
85620 			/* Infinity */
85621 			duk_push_hstring_stridx(thr, DUK_STRIDX_INFINITY);
85622 		}
85623 		return;
85624 	} else if (c == DUK_FP_ZERO) {
85625 		/* We can't shortcut zero here if it goes through special formatting
85626 		 * (such as forced exponential notation).
85627 		 */
85628 		;
85629 	}
85630 
85631 	/*
85632 	 *  Handle integers in 32-bit range (that is, [-(2**32-1),2**32-1])
85633 	 *  specially, as they're very likely for embedded programs.  This
85634 	 *  is now done for all radix values.  We must be careful not to use
85635 	 *  the fast path when special formatting (e.g. forced exponential)
85636 	 *  is in force.
85637 	 *
85638 	 *  XXX: could save space by supporting radix 10 only and using
85639 	 *  sprintf "%lu" for the fast path and for exponent formatting.
85640 	 */
85641 
85642 	uval = duk_double_to_uint32_t(x);
85643 	if (((double) uval) == x &&  /* integer number in range */
85644 	    flags == 0) {            /* no special formatting */
85645 		/* use bigint area as a temp */
85646 		duk_uint8_t *buf = (duk_uint8_t *) (&nc_ctx->f);
85647 		duk_uint8_t *p = buf;
85648 
85649 		DUK_ASSERT(DUK__NUMCONV_CTX_BIGINTS_SIZE >= 32 + 1);  /* max size: radix=2 + sign */
85650 		if (neg && uval != 0) {
85651 			/* no negative sign for zero */
85652 			*p++ = (duk_uint8_t) '-';
85653 		}
85654 		p += duk__dragon4_format_uint32(p, uval, radix);
85655 		duk_push_lstring(thr, (const char *) buf, (duk_size_t) (p - buf));
85656 		return;
85657 	}
85658 
85659 	/*
85660 	 *  Dragon4 setup.
85661 	 *
85662 	 *  Convert double from IEEE representation for conversion;
85663 	 *  normal finite values have an implicit leading 1-bit.  The
85664 	 *  slow path algorithm doesn't handle zero, so zero is special
85665 	 *  cased here but still creates a valid nc_ctx, and goes
85666 	 *  through normal formatting in case special formatting has
85667 	 *  been requested (e.g. forced exponential format: 0 -> "0e+0").
85668 	 */
85669 
85670 	/* Would be nice to bulk clear the allocation, but the context
85671 	 * is 1-2 kilobytes and nothing should rely on it being zeroed.
85672 	 */
85673 #if 0
85674 	duk_memzero((void *) nc_ctx, sizeof(*nc_ctx));  /* slow init, do only for slow path cases */
85675 #endif
85676 
85677 	nc_ctx->is_s2n = 0;
85678 	nc_ctx->b = 2;
85679 	nc_ctx->B = radix;
85680 	nc_ctx->abs_pos = 0;
85681 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
85682 		nc_ctx->is_fixed = 1;
85683 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
85684 			/* absolute req_digits; e.g. digits = 1 -> last digit is 0,
85685 			 * but add an extra digit for rounding.
85686 			 */
85687 			nc_ctx->abs_pos = 1;
85688 			nc_ctx->req_digits = (-digits + 1) - 1;
85689 		} else {
85690 			nc_ctx->req_digits = digits + 1;
85691 		}
85692 	} else {
85693 		nc_ctx->is_fixed = 0;
85694 		nc_ctx->req_digits = 0;
85695 	}
85696 
85697 	if (c == DUK_FP_ZERO) {
85698 		/* Zero special case: fake requested number of zero digits; ensure
85699 		 * no sign bit is printed.  Relative and absolute fixed format
85700 		 * require separate handling.
85701 		 */
85702 		duk_small_int_t count;
85703 		if (nc_ctx->is_fixed) {
85704 			if (nc_ctx->abs_pos) {
85705 				count = digits + 2;  /* lead zero + 'digits' fractions + 1 for rounding */
85706 			} else {
85707 				count = digits + 1;  /* + 1 for rounding */
85708 			}
85709 		} else {
85710 			count = 1;
85711 		}
85712 		DUK_DDD(DUK_DDDPRINT("count=%ld", (long) count));
85713 		DUK_ASSERT(count >= 1);
85714 		duk_memzero((void *) nc_ctx->digits, (size_t) count);
85715 		nc_ctx->count = count;
85716 		nc_ctx->k = 1;  /* 0.000... */
85717 		neg = 0;
85718 		goto zero_skip;
85719 	}
85720 
85721 	duk__dragon4_double_to_ctx(nc_ctx, x);   /* -> sets 'f' and 'e' */
85722 	DUK__BI_PRINT("f", &nc_ctx->f);
85723 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
85724 
85725 	/*
85726 	 *  Dragon4 slow path digit generation.
85727 	 */
85728 
85729 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
85730 
85731 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
85732 	DUK__BI_PRINT("r", &nc_ctx->r);
85733 	DUK__BI_PRINT("s", &nc_ctx->s);
85734 	DUK__BI_PRINT("mp", &nc_ctx->mp);
85735 	DUK__BI_PRINT("mm", &nc_ctx->mm);
85736 
85737 	duk__dragon4_scale(nc_ctx);
85738 
85739 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
85740 	DUK__BI_PRINT("r", &nc_ctx->r);
85741 	DUK__BI_PRINT("s", &nc_ctx->s);
85742 	DUK__BI_PRINT("mp", &nc_ctx->mp);
85743 	DUK__BI_PRINT("mm", &nc_ctx->mm);
85744 
85745 	duk__dragon4_generate(nc_ctx);
85746 
85747 	/*
85748 	 *  Convert and push final string.
85749 	 */
85750 
85751  zero_skip:
85752 
85753 	if (flags & DUK_N2S_FLAG_FIXED_FORMAT) {
85754 		/* Perform fixed-format rounding. */
85755 		duk_small_int_t roundpos;
85756 		if (flags & DUK_N2S_FLAG_FRACTION_DIGITS) {
85757 			/* 'roundpos' is relative to nc_ctx->k and increases to the right
85758 			 * (opposite of how 'k' changes).
85759 			 */
85760 			roundpos = -digits;  /* absolute position for digit considered for rounding */
85761 			roundpos = nc_ctx->k - roundpos;
85762 		} else {
85763 			roundpos = digits;
85764 		}
85765 		DUK_DDD(DUK_DDDPRINT("rounding: k=%ld, count=%ld, digits=%ld, roundpos=%ld",
85766 		                     (long) nc_ctx->k, (long) nc_ctx->count, (long) digits, (long) roundpos));
85767 		(void) duk__dragon4_fixed_format_round(nc_ctx, roundpos);
85768 
85769 		/* Note: 'count' is currently not adjusted by rounding (i.e. the
85770 		 * digits are not "chopped off".  That shouldn't matter because
85771 		 * the digit position (absolute or relative) is passed on to the
85772 		 * convert-and-push function.
85773 		 */
85774 	}
85775 
85776 	duk__dragon4_convert_and_push(nc_ctx, thr, radix, digits, flags, neg);
85777 }
85778 
85779 /*
85780  *  Exposed string-to-number API
85781  *
85782  *  Input: [ string ]
85783  *  Output: [ number ]
85784  *
85785  *  If number parsing fails, a NaN is pushed as the result.  If number parsing
85786  *  fails due to an internal error, an InternalError is thrown.
85787  */
85788 
85789 DUK_INTERNAL void duk_numconv_parse(duk_hthread *thr, duk_small_int_t radix, duk_small_uint_t flags) {
85790 	duk__numconv_stringify_ctx nc_ctx_alloc;  /* large context; around 2kB now */
85791 	duk__numconv_stringify_ctx *nc_ctx = &nc_ctx_alloc;
85792 	duk_double_t res;
85793 	duk_hstring *h_str;
85794 	duk_int_t expt;
85795 	duk_bool_t expt_neg;
85796 	duk_small_int_t expt_adj;
85797 	duk_small_int_t neg;
85798 	duk_small_int_t dig;
85799 	duk_small_int_t dig_whole;
85800 	duk_small_int_t dig_lzero;
85801 	duk_small_int_t dig_frac;
85802 	duk_small_int_t dig_expt;
85803 	duk_small_int_t dig_prec;
85804 	const duk__exp_limits *explim;
85805 	const duk_uint8_t *p;
85806 	duk_small_int_t ch;
85807 
85808 	DUK_DDD(DUK_DDDPRINT("parse number: %!T, radix=%ld, flags=0x%08lx",
85809 	                     (duk_tval *) duk_get_tval(thr, -1),
85810 	                     (long) radix, (unsigned long) flags));
85811 
85812 	DUK_ASSERT(radix >= 2 && radix <= 36);
85813 	DUK_ASSERT(radix - 2 < (duk_small_int_t) sizeof(duk__str2num_digits_for_radix));
85814 
85815 	/*
85816 	 *  Preliminaries: trim, sign, Infinity check
85817 	 *
85818 	 *  We rely on the interned string having a NUL terminator, which will
85819 	 *  cause a parse failure wherever it is encountered.  As a result, we
85820 	 *  don't need separate pointer checks.
85821 	 *
85822 	 *  There is no special parsing for 'NaN' in the specification although
85823 	 *  'Infinity' (with an optional sign) is allowed in some contexts.
85824 	 *  Some contexts allow plus/minus sign, while others only allow the
85825 	 *  minus sign (like JSON.parse()).
85826 	 *
85827 	 *  Automatic hex number detection (leading '0x' or '0X') and octal
85828 	 *  number detection (leading '0' followed by at least one octal digit)
85829 	 *  is done here too.
85830 	 *
85831 	 *  Symbols are not explicitly rejected here (that's up to the caller).
85832 	 *  If a symbol were passed here, it should ultimately safely fail
85833 	 *  parsing due to a syntax error.
85834 	 */
85835 
85836 	if (flags & DUK_S2N_FLAG_TRIM_WHITE) {
85837 		/* Leading / trailing whitespace is sometimes accepted and
85838 		 * sometimes not.  After white space trimming, all valid input
85839 		 * characters are pure ASCII.
85840 		 */
85841 		duk_trim(thr, -1);
85842 	}
85843 	h_str = duk_require_hstring(thr, -1);
85844 	DUK_ASSERT(h_str != NULL);
85845 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_str);
85846 
85847 	neg = 0;
85848 	ch = *p;
85849 	if (ch == (duk_small_int_t) '+') {
85850 		if ((flags & DUK_S2N_FLAG_ALLOW_PLUS) == 0) {
85851 			DUK_DDD(DUK_DDDPRINT("parse failed: leading plus sign not allowed"));
85852 			goto parse_fail;
85853 		}
85854 		p++;
85855 	} else if (ch == (duk_small_int_t) '-') {
85856 		if ((flags & DUK_S2N_FLAG_ALLOW_MINUS) == 0) {
85857 			DUK_DDD(DUK_DDDPRINT("parse failed: leading minus sign not allowed"));
85858 			goto parse_fail;
85859 		}
85860 		p++;
85861 		neg = 1;
85862 	}
85863 
85864 	if ((flags & DUK_S2N_FLAG_ALLOW_INF) && DUK_STRNCMP((const char *) p, "Infinity", 8) == 0) {
85865 		/* Don't check for Infinity unless the context allows it.
85866 		 * 'Infinity' is a valid integer literal in e.g. base-36:
85867 		 *
85868 		 *   parseInt('Infinity', 36)
85869 		 *   1461559270678
85870 		 */
85871 
85872 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0 && p[8] != DUK_ASC_NUL) {
85873 			DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage after matching 'Infinity' not allowed"));
85874 			goto parse_fail;
85875 		} else {
85876 			res = DUK_DOUBLE_INFINITY;
85877 			goto negcheck_and_ret;
85878 		}
85879 	}
85880 	ch = *p;
85881 	if (ch == (duk_small_int_t) '0') {
85882 		duk_small_int_t detect_radix = 0;
85883 		ch = DUK_LOWERCASE_CHAR_ASCII(p[1]);  /* 'x' or 'X' -> 'x' */
85884 		if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_HEX_INT) && ch == DUK_ASC_LC_X) {
85885 			DUK_DDD(DUK_DDDPRINT("detected 0x/0X hex prefix, changing radix and preventing fractions and exponent"));
85886 			detect_radix = 16;
85887 #if 0
85888 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_LEGACY_OCT_INT) &&
85889 		           (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9')) {
85890 			DUK_DDD(DUK_DDDPRINT("detected 0n oct prefix, changing radix and preventing fractions and exponent"));
85891 			detect_radix = 8;
85892 
85893 			/* NOTE: if this legacy octal case is added back, it has
85894 			 * different flags and 'p' advance so this needs to be
85895 			 * reworked.
85896 			 */
85897 			flags |= DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO;  /* interpret e.g. '09' as '0', not NaN */
85898 			p += 1;
85899 #endif
85900 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_OCT_INT) && ch == DUK_ASC_LC_O) {
85901 			DUK_DDD(DUK_DDDPRINT("detected 0o oct prefix, changing radix and preventing fractions and exponent"));
85902 			detect_radix = 8;
85903 		} else if ((flags & DUK_S2N_FLAG_ALLOW_AUTO_BIN_INT) && ch == DUK_ASC_LC_B) {
85904 			DUK_DDD(DUK_DDDPRINT("detected 0b bin prefix, changing radix and preventing fractions and exponent"));
85905 			detect_radix = 2;
85906 		}
85907 		if (detect_radix > 0) {
85908 			radix = detect_radix;
85909 			/* Clear empty as zero flag: interpret e.g. '0x' and '0xg' as a NaN (= parse error) */
85910 			flags &= ~(DUK_S2N_FLAG_ALLOW_EXP | DUK_S2N_FLAG_ALLOW_EMPTY_FRAC |
85911 			           DUK_S2N_FLAG_ALLOW_FRAC | DUK_S2N_FLAG_ALLOW_NAKED_FRAC |
85912 			           DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO);
85913 			flags |= DUK_S2N_FLAG_ALLOW_LEADING_ZERO;  /* allow e.g. '0x0009' and '0b00010001' */
85914 			p += 2;
85915 		}
85916 	}
85917 
85918 	/*
85919 	 *  Scan number and setup for Dragon4.
85920 	 *
85921 	 *  The fast path case is detected during setup: an integer which
85922 	 *  can be converted without rounding, no net exponent.  The fast
85923 	 *  path could be implemented as a separate scan, but may not really
85924 	 *  be worth it: the multiplications for building 'f' are not
85925 	 *  expensive when 'f' is small.
85926 	 *
85927 	 *  The significand ('f') must contain enough bits of (apparent)
85928 	 *  accuracy, so that Dragon4 will generate enough binary output digits.
85929 	 *  For decimal numbers, this means generating a 20-digit significand,
85930 	 *  which should yield enough practical accuracy to parse IEEE doubles.
85931 	 *  In fact, the ECMAScript specification explicitly allows an
85932 	 *  implementation to treat digits beyond 20 as zeroes (and even
85933 	 *  to round the 20th digit upwards).  For non-decimal numbers, the
85934 	 *  appropriate number of digits has been precomputed for comparable
85935 	 *  accuracy.
85936 	 *
85937 	 *  Digit counts:
85938 	 *
85939 	 *    [ dig_lzero ]
85940 	 *      |
85941 	 *     .+-..---[ dig_prec ]----.
85942 	 *     |  ||                   |
85943 	 *     0000123.456789012345678901234567890e+123456
85944 	 *     |     | |                         |  |    |
85945 	 *     `--+--' `------[ dig_frac ]-------'  `-+--'
85946 	 *        |                                   |
85947 	 *    [ dig_whole ]                       [ dig_expt ]
85948 	 *
85949 	 *    dig_frac and dig_expt are -1 if not present
85950 	 *    dig_lzero is only computed for whole number part
85951 	 *
85952 	 *  Parsing state
85953 	 *
85954 	 *     Parsing whole part      dig_frac < 0 AND dig_expt < 0
85955 	 *     Parsing fraction part   dig_frac >= 0 AND dig_expt < 0
85956 	 *     Parsing exponent part   dig_expt >= 0   (dig_frac may be < 0 or >= 0)
85957 	 *
85958 	 *  Note: in case we hit an implementation limit (like exponent range),
85959 	 *  we should throw an error, NOT return NaN or Infinity.  Even with
85960 	 *  very large exponent (or significand) values the final result may be
85961 	 *  finite, so NaN/Infinity would be incorrect.
85962 	 */
85963 
85964 	duk__bi_set_small(&nc_ctx->f, 0);
85965 	dig_prec = 0;
85966 	dig_lzero = 0;
85967 	dig_whole = 0;
85968 	dig_frac = -1;
85969 	dig_expt = -1;
85970 	expt = 0;
85971 	expt_adj = 0;  /* essentially tracks digit position of lowest 'f' digit */
85972 	expt_neg = 0;
85973 	for (;;) {
85974 		ch = *p++;
85975 
85976 		DUK_DDD(DUK_DDDPRINT("parse digits: p=%p, ch='%c' (%ld), expt=%ld, expt_adj=%ld, "
85977 		                     "dig_whole=%ld, dig_frac=%ld, dig_expt=%ld, dig_lzero=%ld, dig_prec=%ld",
85978 		                     (const void *) p, (int) ((ch >= 0x20 && ch <= 0x7e) ? ch : '?'), (long) ch,
85979 		                     (long) expt, (long) expt_adj, (long) dig_whole, (long) dig_frac,
85980 		                     (long) dig_expt, (long) dig_lzero, (long) dig_prec));
85981 		DUK__BI_PRINT("f", &nc_ctx->f);
85982 
85983 		/* Most common cases first. */
85984 		if (ch >= (duk_small_int_t) '0' && ch <= (duk_small_int_t) '9') {
85985 			dig = (duk_small_int_t) ch - '0' + 0;
85986 		} else if (ch == (duk_small_int_t) '.') {
85987 			/* A leading digit is not required in some cases, e.g. accept ".123".
85988 			 * In other cases (JSON.parse()) a leading digit is required.  This
85989 			 * is checked for after the loop.
85990 			 */
85991 			if (dig_frac >= 0 || dig_expt >= 0) {
85992 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
85993 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid period)"));
85994 					break;
85995 				} else {
85996 					DUK_DDD(DUK_DDDPRINT("parse failed: period not allowed"));
85997 					goto parse_fail;
85998 				}
85999 			}
86000 
86001 			if ((flags & DUK_S2N_FLAG_ALLOW_FRAC) == 0) {
86002 				/* Some contexts don't allow fractions at all; this can't be a
86003 				 * post-check because the state ('f' and expt) would be incorrect.
86004 				 */
86005 				if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86006 					DUK_DDD(DUK_DDDPRINT("garbage termination (invalid first period)"));
86007 					break;
86008 				} else {
86009 					DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed"));
86010 				}
86011 			}
86012 
86013 			DUK_DDD(DUK_DDDPRINT("start fraction part"));
86014 			dig_frac = 0;
86015 			continue;
86016 		} else if (ch == (duk_small_int_t) 0) {
86017 			DUK_DDD(DUK_DDDPRINT("NUL termination"));
86018 			break;
86019 		} else if ((flags & DUK_S2N_FLAG_ALLOW_EXP) &&
86020 		           dig_expt < 0 && (ch == (duk_small_int_t) 'e' || ch == (duk_small_int_t) 'E')) {
86021 			/* Note: we don't parse back exponent notation for anything else
86022 			 * than radix 10, so this is not an ambiguous check (e.g. hex
86023 			 * exponent values may have 'e' either as a significand digit
86024 			 * or as an exponent separator).
86025 			 *
86026 			 * If the exponent separator occurs twice, 'e' will be interpreted
86027 			 * as a digit (= 14) and will be rejected as an invalid decimal
86028 			 * digit.
86029 			 */
86030 
86031 			DUK_DDD(DUK_DDDPRINT("start exponent part"));
86032 
86033 			/* Exponent without a sign or with a +/- sign is accepted
86034 			 * by all call sites (even JSON.parse()).
86035 			 */
86036 			ch = *p;
86037 			if (ch == (duk_small_int_t) '-') {
86038 				expt_neg = 1;
86039 				p++;
86040 			} else if (ch == (duk_small_int_t) '+') {
86041 				p++;
86042 			}
86043 			dig_expt = 0;
86044 			continue;
86045 		} else if (ch >= (duk_small_int_t) 'a' && ch <= (duk_small_int_t) 'z') {
86046 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'a' + 0x0a);
86047 		} else if (ch >= (duk_small_int_t) 'A' && ch <= (duk_small_int_t) 'Z') {
86048 			dig = (duk_small_int_t) (ch - (duk_small_int_t) 'A' + 0x0a);
86049 		} else {
86050 			dig = 255;  /* triggers garbage digit check below */
86051 		}
86052 		DUK_ASSERT((dig >= 0 && dig <= 35) || dig == 255);
86053 
86054 		if (dig >= radix) {
86055 			if (flags & DUK_S2N_FLAG_ALLOW_GARBAGE) {
86056 				DUK_DDD(DUK_DDDPRINT("garbage termination"));
86057 				break;
86058 			} else {
86059 				DUK_DDD(DUK_DDDPRINT("parse failed: trailing garbage or invalid digit"));
86060 				goto parse_fail;
86061 			}
86062 		}
86063 
86064 		if (dig_expt < 0) {
86065 			/* whole or fraction digit */
86066 
86067 			if (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86068 				/* significant from precision perspective */
86069 
86070 				duk_small_int_t f_zero = duk__bi_is_zero(&nc_ctx->f);
86071 				if (f_zero && dig == 0) {
86072 					/* Leading zero is not counted towards precision digits; not
86073 					 * in the integer part, nor in the fraction part.
86074 					 */
86075 					if (dig_frac < 0) {
86076 						dig_lzero++;
86077 					}
86078 				} else {
86079 					/* XXX: join these ops (multiply-accumulate), but only if
86080 					 * code footprint decreases.
86081 					 */
86082 					duk__bi_mul_small(&nc_ctx->t1, &nc_ctx->f, (duk_uint32_t) radix);
86083 					duk__bi_add_small(&nc_ctx->f, &nc_ctx->t1, (duk_uint32_t) dig);
86084 					dig_prec++;
86085 				}
86086 			} else {
86087 				/* Ignore digits beyond a radix-specific limit, but note them
86088 				 * in expt_adj.
86089 				 */
86090 				expt_adj++;
86091 			}
86092 
86093 			if (dig_frac >= 0) {
86094 				dig_frac++;
86095 				expt_adj--;
86096 			} else {
86097 				dig_whole++;
86098 			}
86099 		} else {
86100 			/* exponent digit */
86101 
86102 			DUK_ASSERT(radix == 10);
86103 			expt = expt * radix + dig;
86104 			if (expt > DUK_S2N_MAX_EXPONENT) {
86105 				/* Impose a reasonable exponent limit, so that exp
86106 				 * doesn't need to get tracked using a bigint.
86107 				 */
86108 				DUK_DDD(DUK_DDDPRINT("parse failed: exponent too large"));
86109 				goto parse_explimit_error;
86110 			}
86111 			dig_expt++;
86112 		}
86113 	}
86114 
86115 	/* Leading zero. */
86116 
86117 	if (dig_lzero > 0 && dig_whole > 1) {
86118 		if ((flags & DUK_S2N_FLAG_ALLOW_LEADING_ZERO) == 0) {
86119 			DUK_DDD(DUK_DDDPRINT("parse failed: leading zeroes not allowed in integer part"));
86120 			goto parse_fail;
86121 		}
86122 	}
86123 
86124 	/* Validity checks for various fraction formats ("0.1", ".1", "1.", "."). */
86125 
86126 	if (dig_whole == 0) {
86127 		if (dig_frac == 0) {
86128 			/* "." is not accepted in any format */
86129 			DUK_DDD(DUK_DDDPRINT("parse failed: plain period without leading or trailing digits"));
86130 			goto parse_fail;
86131 		} else if (dig_frac > 0) {
86132 			/* ".123" */
86133 			if ((flags & DUK_S2N_FLAG_ALLOW_NAKED_FRAC) == 0) {
86134 				DUK_DDD(DUK_DDDPRINT("parse failed: fraction part not allowed without "
86135 				                     "leading integer digit(s)"));
86136 				goto parse_fail;
86137 			}
86138 		} else {
86139 			/* empty ("") is allowed in some formats (e.g. Number(''), as zero */
86140 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_AS_ZERO) == 0) {
86141 				DUK_DDD(DUK_DDDPRINT("parse failed: empty string not allowed (as zero)"));
86142 				goto parse_fail;
86143 			}
86144 		}
86145 	} else {
86146 		if (dig_frac == 0) {
86147 			/* "123." is allowed in some formats */
86148 			if ((flags & DUK_S2N_FLAG_ALLOW_EMPTY_FRAC) == 0) {
86149 				DUK_DDD(DUK_DDDPRINT("parse failed: empty fractions"));
86150 				goto parse_fail;
86151 			}
86152 		} else if (dig_frac > 0) {
86153 			/* "123.456" */
86154 			;
86155 		} else {
86156 			/* "123" */
86157 			;
86158 		}
86159 	}
86160 
86161 	/* Exponent without digits (e.g. "1e" or "1e+").  If trailing garbage is
86162 	 * allowed, ignore exponent part as garbage (= parse as "1", i.e. exp 0).
86163 	 */
86164 
86165 	if (dig_expt == 0) {
86166 		if ((flags & DUK_S2N_FLAG_ALLOW_GARBAGE) == 0) {
86167 			DUK_DDD(DUK_DDDPRINT("parse failed: empty exponent"));
86168 			goto parse_fail;
86169 		}
86170 		DUK_ASSERT(expt == 0);
86171 	}
86172 
86173 	if (expt_neg) {
86174 		expt = -expt;
86175 	}
86176 	DUK_DDD(DUK_DDDPRINT("expt=%ld, expt_adj=%ld, net exponent -> %ld",
86177 	                     (long) expt, (long) expt_adj, (long) (expt + expt_adj)));
86178 	expt += expt_adj;
86179 
86180 	/* Fast path check. */
86181 
86182 	if (nc_ctx->f.n <= 1 &&   /* 32-bit value */
86183 	    expt == 0    /* no net exponent */) {
86184 		/* Fast path is triggered for no exponent and also for balanced exponent
86185 		 * and fraction parts, e.g. for "1.23e2" == "123".  Remember to respect
86186 		 * zero sign.
86187 		 */
86188 
86189 		/* XXX: could accept numbers larger than 32 bits, e.g. up to 53 bits? */
86190 		DUK_DDD(DUK_DDDPRINT("fast path number parse"));
86191 		if (nc_ctx->f.n == 1) {
86192 			res = (double) nc_ctx->f.v[0];
86193 		} else {
86194 			res = 0.0;
86195 		}
86196 		goto negcheck_and_ret;
86197 	}
86198 
86199 	/* Significand ('f') padding. */
86200 
86201 	while (dig_prec < duk__str2num_digits_for_radix[radix - 2]) {
86202 		/* Pad significand with "virtual" zero digits so that Dragon4 will
86203 		 * have enough (apparent) precision to work with.
86204 		 */
86205 		DUK_DDD(DUK_DDDPRINT("dig_prec=%ld, pad significand with zero", (long) dig_prec));
86206 		duk__bi_mul_small_copy(&nc_ctx->f, (duk_uint32_t) radix, &nc_ctx->t1);
86207 		DUK__BI_PRINT("f", &nc_ctx->f);
86208 		expt--;
86209 		dig_prec++;
86210 	}
86211 
86212 	DUK_DDD(DUK_DDDPRINT("final exponent: %ld", (long) expt));
86213 
86214 	/* Detect zero special case. */
86215 
86216 	if (nc_ctx->f.n == 0) {
86217 		/* This may happen even after the fast path check, if exponent is
86218 		 * not balanced (e.g. "0e1").  Remember to respect zero sign.
86219 		 */
86220 		DUK_DDD(DUK_DDDPRINT("significand is zero"));
86221 		res = 0.0;
86222 		goto negcheck_and_ret;
86223 	}
86224 
86225 
86226 	/* Quick reject of too large or too small exponents.  This check
86227 	 * would be incorrect for zero (e.g. "0e1000" is zero, not Infinity)
86228 	 * so zero check must be above.
86229 	 */
86230 
86231 	explim = &duk__str2num_exp_limits[radix - 2];
86232 	if (expt > explim->upper) {
86233 		DUK_DDD(DUK_DDDPRINT("exponent too large -> infinite"));
86234 		res = (duk_double_t) DUK_DOUBLE_INFINITY;
86235 		goto negcheck_and_ret;
86236 	} else if (expt < explim->lower) {
86237 		DUK_DDD(DUK_DDDPRINT("exponent too small -> zero"));
86238 		res = (duk_double_t) 0.0;
86239 		goto negcheck_and_ret;
86240 	}
86241 
86242 	nc_ctx->is_s2n = 1;
86243 	nc_ctx->e = expt;
86244 	nc_ctx->b = radix;
86245 	nc_ctx->B = 2;
86246 	nc_ctx->is_fixed = 1;
86247 	nc_ctx->abs_pos = 0;
86248 	nc_ctx->req_digits = 53 + 1;
86249 
86250 	DUK__BI_PRINT("f", &nc_ctx->f);
86251 	DUK_DDD(DUK_DDDPRINT("e=%ld", (long) nc_ctx->e));
86252 
86253 	/*
86254 	 *  Dragon4 slow path (binary) digit generation.
86255 	 *  An extra digit is generated for rounding.
86256 	 */
86257 
86258 	duk__dragon4_prepare(nc_ctx);  /* setup many variables in nc_ctx */
86259 
86260 	DUK_DDD(DUK_DDDPRINT("after prepare:"));
86261 	DUK__BI_PRINT("r", &nc_ctx->r);
86262 	DUK__BI_PRINT("s", &nc_ctx->s);
86263 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86264 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86265 
86266 	duk__dragon4_scale(nc_ctx);
86267 
86268 	DUK_DDD(DUK_DDDPRINT("after scale; k=%ld", (long) nc_ctx->k));
86269 	DUK__BI_PRINT("r", &nc_ctx->r);
86270 	DUK__BI_PRINT("s", &nc_ctx->s);
86271 	DUK__BI_PRINT("mp", &nc_ctx->mp);
86272 	DUK__BI_PRINT("mm", &nc_ctx->mm);
86273 
86274 	duk__dragon4_generate(nc_ctx);
86275 
86276 	DUK_ASSERT(nc_ctx->count == 53 + 1);
86277 
86278 	/*
86279 	 *  Convert binary digits into an IEEE double.  Need to handle
86280 	 *  denormals and rounding correctly.
86281 	 *
86282 	 *  Some call sites currently assume the result is always a
86283 	 *  non-fastint double.  If this is changed, check all call
86284 	 *  sites.
86285 	 */
86286 
86287 	duk__dragon4_ctx_to_double(nc_ctx, &res);
86288 	goto negcheck_and_ret;
86289 
86290  negcheck_and_ret:
86291 	if (neg) {
86292 		res = -res;
86293 	}
86294 	duk_pop(thr);
86295 	duk_push_number(thr, (double) res);
86296 	DUK_DDD(DUK_DDDPRINT("result: %!T", (duk_tval *) duk_get_tval(thr, -1)));
86297 	return;
86298 
86299  parse_fail:
86300 	DUK_DDD(DUK_DDDPRINT("parse failed"));
86301 	duk_pop(thr);
86302 	duk_push_nan(thr);
86303 	return;
86304 
86305  parse_explimit_error:
86306 	DUK_DDD(DUK_DDDPRINT("parse failed, internal error, can't return a value"));
86307 	DUK_ERROR_RANGE(thr, "exponent too large");
86308 	DUK_WO_NORETURN(return;);
86309 }
86310 
86311 /* automatic undefs */
86312 #undef DUK__BI_MAX_PARTS
86313 #undef DUK__BI_PRINT
86314 #undef DUK__DIGITCHAR
86315 #undef DUK__DRAGON4_OUTPUT_PREINC
86316 #undef DUK__IEEE_DOUBLE_EXP_BIAS
86317 #undef DUK__IEEE_DOUBLE_EXP_MIN
86318 #undef DUK__MAX_FORMATTED_LENGTH
86319 #undef DUK__MAX_OUTPUT_DIGITS
86320 #undef DUK__NO_EXP
86321 #undef DUK__NUMCONV_CTX_BIGINTS_SIZE
86322 #undef DUK__NUMCONV_CTX_NUM_BIGINTS
86323 #line 1 "duk_regexp_compiler.c"
86324 /*
86325  *  Regexp compilation.
86326  *
86327  *  See doc/regexp.rst for a discussion of the compilation approach and
86328  *  current limitations.
86329  *
86330  *  Regexp bytecode assumes jumps can be expressed with signed 32-bit
86331  *  integers.  Consequently the bytecode size must not exceed 0x7fffffffL.
86332  *  The implementation casts duk_size_t (buffer size) to duk_(u)int32_t
86333  *  in many places.  Although this could be changed, the bytecode format
86334  *  limit would still prevent regexps exceeding the signed 32-bit limit
86335  *  from working.
86336  *
86337  *  XXX: The implementation does not prevent bytecode from exceeding the
86338  *  maximum supported size.  This could be done by limiting the maximum
86339  *  input string size (assuming an upper bound can be computed for number
86340  *  of bytecode bytes emitted per input byte) or checking buffer maximum
86341  *  size when emitting bytecode (slower).
86342  */
86343 
86344 /* #include duk_internal.h -> already included */
86345 
86346 #if defined(DUK_USE_REGEXP_SUPPORT)
86347 
86348 /*
86349  *  Helper macros
86350  */
86351 
86352 #define DUK__RE_INITIAL_BUFSIZE 64
86353 
86354 #define DUK__RE_BUFLEN(re_ctx) \
86355 	DUK_BW_GET_SIZE(re_ctx->thr, &re_ctx->bw)
86356 
86357 /*
86358  *  Disjunction struct: result of parsing a disjunction
86359  */
86360 
86361 typedef struct {
86362 	/* Number of characters that the atom matches (e.g. 3 for 'abc'),
86363 	 * -1 if atom is complex and number of matched characters either
86364 	 * varies or is not known.
86365 	 */
86366 	duk_int32_t charlen;
86367 
86368 #if 0
86369 	/* These are not needed to implement quantifier capture handling,
86370 	 * but might be needed at some point.
86371 	 */
86372 
86373 	/* re_ctx->captures at start and end of atom parsing.
86374 	 * Since 'captures' indicates highest capture number emitted
86375 	 * so far in a DUK_REOP_SAVE, the captures numbers saved by
86376 	 * the atom are: ]start_captures,end_captures].
86377 	 */
86378 	duk_uint32_t start_captures;
86379 	duk_uint32_t end_captures;
86380 #endif
86381 } duk__re_disjunction_info;
86382 
86383 /*
86384  *  Encoding helpers
86385  *
86386  *  Some of the typing is bytecode based, e.g. slice sizes are unsigned 32-bit
86387  *  even though the buffer operations will use duk_size_t.
86388  */
86389 
86390 /* XXX: the insert helpers should ensure that the bytecode result is not
86391  * larger than expected (or at least assert for it).  Many things in the
86392  * bytecode, like skip offsets, won't work correctly if the bytecode is
86393  * larger than say 2G.
86394  */
86395 
86396 DUK_LOCAL duk_uint32_t duk__encode_i32(duk_int32_t x) {
86397 	if (x < 0) {
86398 		return ((duk_uint32_t) (-x)) * 2 + 1;
86399 	} else {
86400 		return ((duk_uint32_t) x) * 2;
86401 	}
86402 }
86403 
86404 /* XXX: return type should probably be duk_size_t, or explicit checks are needed for
86405  * maximum size.
86406  */
86407 DUK_LOCAL duk_uint32_t duk__insert_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_uint32_t x) {
86408 	duk_uint8_t buf[DUK_UNICODE_MAX_XUTF8_LENGTH];
86409 	duk_small_int_t len;
86410 
86411 	len = duk_unicode_encode_xutf8((duk_ucodepoint_t) x, buf);
86412 	DUK_ASSERT(len >= 0);
86413 	DUK_BW_INSERT_ENSURE_BYTES(re_ctx->thr, &re_ctx->bw, offset, buf, (duk_size_t) len);
86414 	return (duk_uint32_t) len;
86415 }
86416 
86417 DUK_LOCAL void duk__append_u32(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
86418 	DUK_BW_WRITE_ENSURE_XUTF8(re_ctx->thr, &re_ctx->bw, x);
86419 }
86420 
86421 DUK_LOCAL void duk__append_7bit(duk_re_compiler_ctx *re_ctx, duk_uint32_t x) {
86422 #if defined(DUK_USE_PREFER_SIZE)
86423 	duk__append_u32(re_ctx, x);
86424 #else
86425 	DUK_ASSERT(x <= 0x7fU);
86426 	DUK_BW_WRITE_ENSURE_U8(re_ctx->thr, &re_ctx->bw, (duk_uint8_t) x);
86427 #endif
86428 }
86429 
86430 #if 0
86431 DUK_LOCAL void duk__append_2bytes(duk_re_compiler_ctx *re_ctx, duk_uint8_t x, duk_uint8_t y) {
86432 	DUK_BW_WRITE_ENSURE_U8_2(re_ctx->thr, &re_ctx->bw, x, y);
86433 }
86434 #endif
86435 
86436 DUK_LOCAL duk_uint32_t duk__insert_i32(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t x) {
86437 	return duk__insert_u32(re_ctx, offset, duk__encode_i32(x));
86438 }
86439 
86440 DUK_LOCAL void duk__append_reop(duk_re_compiler_ctx *re_ctx, duk_uint32_t reop) {
86441 	DUK_ASSERT(reop <= 0x7fU);
86442 	(void) duk__append_7bit(re_ctx, reop);
86443 }
86444 
86445 #if 0  /* unused */
86446 DUK_LOCAL void duk__append_i32(duk_re_compiler_ctx *re_ctx, duk_int32_t x) {
86447 	duk__append_u32(re_ctx, duk__encode_i32(x));
86448 }
86449 #endif
86450 
86451 /* special helper for emitting u16 lists (used for character ranges for built-in char classes) */
86452 DUK_LOCAL void duk__append_u16_list(duk_re_compiler_ctx *re_ctx, const duk_uint16_t *values, duk_uint32_t count) {
86453 	/* Call sites don't need the result length so it's not accumulated. */
86454 	while (count-- > 0) {
86455 		duk__append_u32(re_ctx, (duk_uint32_t) (*values++));
86456 	}
86457 }
86458 
86459 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) {
86460 	DUK_BW_INSERT_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, offset, data_offset, data_length);
86461 }
86462 
86463 DUK_LOCAL void duk__append_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
86464 	DUK_BW_WRITE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
86465 }
86466 
86467 DUK_LOCAL void duk__remove_slice(duk_re_compiler_ctx *re_ctx, duk_uint32_t data_offset, duk_uint32_t data_length) {
86468 	DUK_BW_REMOVE_ENSURE_SLICE(re_ctx->thr, &re_ctx->bw, data_offset, data_length);
86469 }
86470 
86471 /*
86472  *  Insert a jump offset at 'offset' to complete an instruction
86473  *  (the jump offset is always the last component of an instruction).
86474  *  The 'skip' argument must be computed relative to 'offset',
86475  *  -without- taking into account the skip field being inserted.
86476  *
86477  *       ... A B C ins X Y Z ...   (ins may be a JUMP, SPLIT1/SPLIT2, etc)
86478  *   =>  ... A B C ins SKIP X Y Z
86479  *
86480  *  Computing the final (adjusted) skip value, which is relative to the
86481  *  first byte of the next instruction, is a bit tricky because of the
86482  *  variable length UTF-8 encoding.  See doc/regexp.rst for discussion.
86483  */
86484 DUK_LOCAL duk_uint32_t duk__insert_jump_offset(duk_re_compiler_ctx *re_ctx, duk_uint32_t offset, duk_int32_t skip) {
86485 #if 0
86486 	/* Iterative solution. */
86487 	if (skip < 0) {
86488 		duk_small_int_t len;
86489 		/* two encoding attempts suffices */
86490 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip));
86491 		len = duk_unicode_get_xutf8_length((duk_codepoint_t) duk__encode_i32(skip - (duk_int32_t) len));
86492 		DUK_ASSERT(duk_unicode_get_xutf8_length(duk__encode_i32(skip - (duk_int32_t) len)) == len);  /* no change */
86493 		skip -= (duk_int32_t) len;
86494 	}
86495 #endif
86496 
86497 #if defined(DUK_USE_PREFER_SIZE)
86498 	/* Closed form solution, this produces smallest code.
86499 	 * See re_neg_jump_offset (closed2).
86500 	 */
86501 	if (skip < 0) {
86502 		skip--;
86503 		if (skip < -0x3fL) {
86504 			skip--;
86505 		}
86506 		if (skip < -0x3ffL) {
86507 			skip--;
86508 		}
86509 		if (skip < -0x7fffL) {
86510 			skip--;
86511 		}
86512 		if (skip < -0xfffffL) {
86513 			skip--;
86514 		}
86515 		if (skip < -0x1ffffffL) {
86516 			skip--;
86517 		}
86518 		if (skip < -0x3fffffffL) {
86519 			skip--;
86520 		}
86521 	}
86522 #else  /* DUK_USE_PREFER_SIZE */
86523 	/* Closed form solution, this produces fastest code.
86524 	 * See re_neg_jump_offset (closed1).
86525 	 */
86526 	if (skip < 0) {
86527 		if (skip >= -0x3eL) {
86528 			skip -= 1;
86529 		} else if (skip >= -0x3fdL) {
86530 			skip -= 2;
86531 		} else if (skip >= -0x7ffcL) {
86532 			skip -= 3;
86533 		} else if (skip >= -0xffffbL) {
86534 			skip -= 4;
86535 		} else if (skip >= -0x1fffffaL) {
86536 			skip -= 5;
86537 		} else if (skip >= -0x3ffffff9L) {
86538 			skip -= 6;
86539 		} else {
86540 			skip -= 7;
86541 		}
86542 	}
86543 #endif  /* DUK_USE_PREFER_SIZE */
86544 
86545 	return duk__insert_i32(re_ctx, offset, skip);
86546 }
86547 
86548 DUK_LOCAL duk_uint32_t duk__append_jump_offset(duk_re_compiler_ctx *re_ctx, duk_int32_t skip) {
86549 	return (duk_uint32_t) duk__insert_jump_offset(re_ctx, (duk_uint32_t) DUK__RE_BUFLEN(re_ctx), skip);
86550 }
86551 
86552 /*
86553  *  duk_re_range_callback for generating character class ranges.
86554  *
86555  *  When ignoreCase is false, the range is simply emitted as is.  We don't,
86556  *  for instance, eliminate duplicates or overlapping ranges in a character
86557  *  class.
86558  *
86559  *  When ignoreCase is true but the 'direct' flag is set, the caller knows
86560  *  that the range canonicalizes to itself for case insensitive matching,
86561  *  so the range is emitted as is.  This is mainly useful for built-in ranges
86562  *  like \W.
86563  *
86564  *  Otherwise, when ignoreCase is true, the range needs to be normalized
86565  *  through canonicalization.  Unfortunately a canonicalized version of a
86566  *  continuous range is not necessarily continuous (e.g. [x-{] is continuous
86567  *  but [X-{] is not).  As a result, a single input range may expand to a lot
86568  *  of output ranges.  The current algorithm creates the canonicalized ranges
86569  *  footprint efficiently at the cost of compile time execution time; see
86570  *  doc/regexp.rst for discussion, and some more details below.
86571  *
86572  *  Note that the ctx->nranges is a context-wide temporary value.  This is OK
86573  *  because there cannot be multiple character classes being parsed
86574  *  simultaneously.
86575  *
86576  *  More detail on canonicalization:
86577  *
86578  *  Conceptually, a range is canonicalized by scanning the entire range,
86579  *  normalizing each codepoint by converting it to uppercase, and generating
86580  *  a set of result ranges.
86581  *
86582  *  Ideally a minimal set of output ranges would be emitted by merging all
86583  *  possible ranges even if they're emitted out of sequence.  Because the
86584  *  input string is also case normalized during matching, some codepoints
86585  *  never occur at runtime; these "don't care" codepoints can be included or
86586  *  excluded from ranges when merging/optimizing ranges.
86587  *
86588  *  The current algorithm does not do optimal range merging.  Rather, output
86589  *  codepoints are generated in sequence, and when the output codepoints are
86590  *  continuous (CP, CP+1, CP+2, ...), they are merged locally into as large a
86591  *  range as possible.  A small canonicalization bitmap is used to reduce
86592  *  actual codepoint canonicalizations which are quite slow at present.  The
86593  *  bitmap provides a "codepoint block is continuous with respect to
86594  *  canonicalization" for N-codepoint blocks.  This allows blocks to be
86595  *  skipped quickly.
86596  *
86597  *  There are a number of shortcomings and future work here:
86598  *
86599  *    - Individual codepoint normalizations are slow because they involve
86600  *      walking bit-packed rules without a lookup index.
86601  *
86602  *    - The conceptual algorithm needs to canonicalize every codepoint in the
86603  *      input range to figure out the output range(s).  Even with the small
86604  *      canonicalization bitmap the algorithm runs quite slowly for worst case
86605  *      inputs.  There are many data structure alternatives to improve this.
86606  *
86607  *    - While the current algorithm generates maximal output ranges when the
86608  *      output codepoints are emitted linearly, output ranges are not sorted or
86609  *      merged otherwise.  In the worst case a lot of ranges are emitted when
86610  *      most of the ranges could be merged.  In this process one could take
86611  *      advantage of "don't care" codepoints, which are never matched against at
86612  *      runtime due to canonicalization of input codepoints before comparison,
86613  *      to merge otherwise discontinuous output ranges.
86614  *
86615  *    - The runtime data structure is just a linear list of ranges to match
86616  *      against.  This can be quite slow if there are a lot of output ranges.
86617  *      There are various ways to make matching against the ranges faster,
86618  *      e.g. sorting the ranges and using a binary search; skip lists; tree
86619  *      based representations; full or approximate codepoint bitmaps, etc.
86620  *
86621  *    - Only BMP is supported, codepoints above BMP are assumed to canonicalize
86622  *      to themselves.  For now this is one place where we don't want to
86623  *      support chars outside the BMP, because the exhaustive search would be
86624  *      massively larger.  It would be possible to support non-BMP with a
86625  *      different algorithm, or perhaps doing case normalization only at match
86626  *      time.
86627  */
86628 
86629 DUK_LOCAL void duk__regexp_emit_range(duk_re_compiler_ctx *re_ctx, duk_codepoint_t r1, duk_codepoint_t r2) {
86630 	DUK_ASSERT(r2 >= r1);
86631 	duk__append_u32(re_ctx, (duk_uint32_t) r1);
86632 	duk__append_u32(re_ctx, (duk_uint32_t) r2);
86633 	re_ctx->nranges++;
86634 }
86635 
86636 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
86637 /* Find next canonicalization discontinuity (conservative estimate) starting
86638  * from 'start', not exceeding 'end'.  If continuity is fine up to 'end'
86639  * inclusive, returns end.  Minimum possible return value is start.
86640  */
86641 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
86642 	duk_uint_t start_blk;
86643 	duk_uint_t end_blk;
86644 	duk_uint_t blk;
86645 	duk_uint_t offset;
86646 	duk_uint8_t mask;
86647 
86648 	/* Inclusive block range. */
86649 	DUK_ASSERT(start >= 0);
86650 	DUK_ASSERT(end >= 0);
86651 	DUK_ASSERT(end >= start);
86652 	start_blk = (duk_uint_t) (start >> DUK_CANON_BITMAP_BLKSHIFT);
86653 	end_blk = (duk_uint_t) (end >> DUK_CANON_BITMAP_BLKSHIFT);
86654 
86655 	for (blk = start_blk; blk <= end_blk; blk++) {
86656 		offset = blk >> 3;
86657 		mask = 1U << (blk & 0x07);
86658 		if (offset >= sizeof(duk_unicode_re_canon_bitmap)) {
86659 			/* Reached non-BMP range which is assumed continuous. */
86660 			return end;
86661 		}
86662 		DUK_ASSERT(offset < sizeof(duk_unicode_re_canon_bitmap));
86663 		if ((duk_unicode_re_canon_bitmap[offset] & mask) == 0) {
86664 			/* Block is discontinuous, continuity is guaranteed
86665 			 * only up to end of previous block (+1 for exclusive
86666 			 * return value => start of current block).  Start
86667 			 * block requires special handling.
86668 			 */
86669 			if (blk > start_blk) {
86670 				return (duk_codepoint_t) (blk << DUK_CANON_BITMAP_BLKSHIFT);
86671 			} else {
86672 				return start;
86673 			}
86674 		}
86675 	}
86676 	DUK_ASSERT(blk == end_blk + 1);  /* Reached end block which is continuous. */
86677 	return end;
86678 }
86679 #else  /* DUK_USE_REGEXP_CANON_BITMAP */
86680 DUK_LOCAL duk_codepoint_t duk__re_canon_next_discontinuity(duk_codepoint_t start, duk_codepoint_t end) {
86681 	DUK_ASSERT(start >= 0);
86682 	DUK_ASSERT(end >= 0);
86683 	DUK_ASSERT(end >= start);
86684 	if (start >= 0x10000) {
86685 		/* Even without the bitmap, treat non-BMP as continuous. */
86686 		return end;
86687 	}
86688 	return start;
86689 }
86690 #endif  /* DUK_USE_REGEXP_CANON_BITMAP */
86691 
86692 DUK_LOCAL void duk__regexp_generate_ranges(void *userdata, duk_codepoint_t r1, duk_codepoint_t r2, duk_bool_t direct) {
86693 	duk_re_compiler_ctx *re_ctx = (duk_re_compiler_ctx *) userdata;
86694 	duk_codepoint_t r_start;
86695 	duk_codepoint_t r_end;
86696 	duk_codepoint_t i;
86697 	duk_codepoint_t t;
86698 	duk_codepoint_t r_disc;
86699 
86700 	DUK_DD(DUK_DDPRINT("duk__regexp_generate_ranges(): re_ctx=%p, range=[%ld,%ld] direct=%ld",
86701 	                   (void *) re_ctx, (long) r1, (long) r2, (long) direct));
86702 
86703 	DUK_ASSERT(r2 >= r1);  /* SyntaxError for out of order range. */
86704 
86705 	if (direct || (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) == 0) {
86706 		DUK_DD(DUK_DDPRINT("direct or not case sensitive, emit range: [%ld,%ld]", (long) r1, (long) r2));
86707 		duk__regexp_emit_range(re_ctx, r1, r2);
86708 		return;
86709 	}
86710 
86711 	DUK_DD(DUK_DDPRINT("case sensitive, process range: [%ld,%ld]", (long) r1, (long) r2));
86712 
86713 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
86714 	r_end = r_start;
86715 
86716 	for (i = r1 + 1; i <= r2;) {
86717 		/* Input codepoint space processed up to i-1, and
86718 		 * current range in r_{start,end} is up-to-date
86719 		 * (inclusive) and may either break or continue.
86720 		 */
86721 		r_disc = duk__re_canon_next_discontinuity(i, r2);
86722 		DUK_ASSERT(r_disc >= i);
86723 		DUK_ASSERT(r_disc <= r2);
86724 
86725 		r_end += r_disc - i;  /* May be zero. */
86726 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, r_disc);
86727 		if (t == r_end + 1) {
86728 			/* Not actually a discontinuity, continue range
86729 			 * to r_disc and recheck.
86730 			 */
86731 			r_end = t;
86732 		} else {
86733 			duk__regexp_emit_range(re_ctx, r_start, r_end);
86734 			r_start = t;
86735 			r_end = t;
86736 		}
86737 		i = r_disc + 1;  /* Guarantees progress. */
86738 	}
86739 	duk__regexp_emit_range(re_ctx, r_start, r_end);
86740 
86741 #if 0  /* Exhaustive search, very slow. */
86742 	r_start = duk_unicode_re_canonicalize_char(re_ctx->thr, r1);
86743 	r_end = r_start;
86744 	for (i = r1 + 1; i <= r2; i++) {
86745 		t = duk_unicode_re_canonicalize_char(re_ctx->thr, i);
86746 		if (t == r_end + 1) {
86747 			r_end = t;
86748 		} else {
86749 			DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
86750 			duk__append_u32(re_ctx, (duk_uint32_t) r_start);
86751 			duk__append_u32(re_ctx, (duk_uint32_t) r_end);
86752 			re_ctx->nranges++;
86753 			r_start = t;
86754 			r_end = t;
86755 		}
86756 	}
86757 	DUK_DD(DUK_DDPRINT("canonicalized, emit range: [%ld,%ld]", (long) r_start, (long) r_end));
86758 	duk__append_u32(re_ctx, (duk_uint32_t) r_start);
86759 	duk__append_u32(re_ctx, (duk_uint32_t) r_end);
86760 	re_ctx->nranges++;
86761 #endif
86762 }
86763 
86764 /*
86765  *  Parse regexp Disjunction.  Most of regexp compilation happens here.
86766  *
86767  *  Handles Disjunction, Alternative, and Term productions directly without
86768  *  recursion.  The only constructs requiring recursion are positive/negative
86769  *  lookaheads, capturing parentheses, and non-capturing parentheses.
86770  *
86771  *  The function determines whether the entire disjunction is a 'simple atom'
86772  *  (see doc/regexp.rst discussion on 'simple quantifiers') and if so,
86773  *  returns the atom character length which is needed by the caller to keep
86774  *  track of its own atom character length.  A disjunction with more than one
86775  *  alternative is never considered a simple atom (although in some cases
86776  *  that might be the case).
86777  *
86778  *  Return value: simple atom character length or < 0 if not a simple atom.
86779  *  Appends the bytecode for the disjunction matcher to the end of the temp
86780  *  buffer.
86781  *
86782  *  Regexp top level structure is:
86783  *
86784  *    Disjunction = Term*
86785  *                | Term* | Disjunction
86786  *
86787  *    Term = Assertion
86788  *         | Atom
86789  *         | Atom Quantifier
86790  *
86791  *  An empty Term sequence is a valid disjunction alternative (e.g. /|||c||/).
86792  *
86793  *  Notes:
86794  *
86795  *    * Tracking of the 'simple-ness' of the current atom vs. the entire
86796  *      disjunction are separate matters.  For instance, the disjunction
86797  *      may be complex, but individual atoms may be simple.  Furthermore,
86798  *      simple quantifiers are used whenever possible, even if the
86799  *      disjunction as a whole is complex.
86800  *
86801  *    * The estimate of whether an atom is simple is conservative now,
86802  *      and it would be possible to expand it.  For instance, captures
86803  *      cause the disjunction to be marked complex, even though captures
86804  *      -can- be handled by simple quantifiers with some minor modifications.
86805  *
86806  *    * Disjunction 'tainting' as 'complex' is handled at the end of the
86807  *      main for loop collectively for atoms.  Assertions, quantifiers,
86808  *      and '|' tokens need to taint the result manually if necessary.
86809  *      Assertions cannot add to result char length, only atoms (and
86810  *      quantifiers) can; currently quantifiers will taint the result
86811  *      as complex though.
86812  */
86813 
86814 DUK_LOCAL const duk_uint16_t * const duk__re_range_lookup1[3] = {
86815 	duk_unicode_re_ranges_digit,
86816 	duk_unicode_re_ranges_white,
86817 	duk_unicode_re_ranges_wordchar
86818 };
86819 DUK_LOCAL const duk_uint8_t duk__re_range_lookup2[3] = {
86820 	sizeof(duk_unicode_re_ranges_digit) / (2 * sizeof(duk_uint16_t)),
86821 	sizeof(duk_unicode_re_ranges_white) / (2 * sizeof(duk_uint16_t)),
86822 	sizeof(duk_unicode_re_ranges_wordchar) / (2 * sizeof(duk_uint16_t))
86823 };
86824 
86825 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) {
86826 #if 0
86827 	DUK_ASSERT(re_op <= 0x7fUL);
86828 	DUK_ASSERT(count <= 0x7fUL);
86829 	duk__append_2bytes(re_ctx, (duk_uint8_t) re_op, (duk_uint8_t) count);
86830 #endif
86831 	duk__append_reop(re_ctx, re_op);
86832 	duk__append_7bit(re_ctx, count);
86833 	duk__append_u16_list(re_ctx, ranges, count * 2);
86834 }
86835 
86836 DUK_LOCAL void duk__parse_disjunction(duk_re_compiler_ctx *re_ctx, duk_bool_t expect_eof, duk__re_disjunction_info *out_atom_info) {
86837 	duk_int32_t atom_start_offset = -1;                   /* negative -> no atom matched on previous round */
86838 	duk_int32_t atom_char_length = 0;                     /* negative -> complex atom */
86839 	duk_uint32_t atom_start_captures = re_ctx->captures;  /* value of re_ctx->captures at start of atom */
86840 	duk_int32_t unpatched_disjunction_split = -1;
86841 	duk_int32_t unpatched_disjunction_jump = -1;
86842 	duk_uint32_t entry_offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
86843 	duk_int32_t res_charlen = 0;  /* -1 if disjunction is complex, char length if simple */
86844 	duk__re_disjunction_info tmp_disj;
86845 
86846 	DUK_ASSERT(out_atom_info != NULL);
86847 
86848 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
86849 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_COMPILER_RECURSION_LIMIT);
86850 		DUK_WO_NORETURN(return;);
86851 	}
86852 	re_ctx->recursion_depth++;
86853 
86854 #if 0
86855 	out_atom_info->start_captures = re_ctx->captures;
86856 #endif
86857 
86858 	for (;;) {
86859 		/* atom_char_length, atom_start_offset, atom_start_offset reflect the
86860 		 * atom matched on the previous loop.  If a quantifier is encountered
86861 		 * on this loop, these are needed to handle the quantifier correctly.
86862 		 * new_atom_char_length etc are for the atom parsed on this round;
86863 		 * they're written to atom_char_length etc at the end of the round.
86864 		 */
86865 		duk_int32_t new_atom_char_length;   /* char length of the atom parsed in this loop */
86866 		duk_int32_t new_atom_start_offset;  /* bytecode start offset of the atom parsed in this loop
86867 		                                     * (allows quantifiers to copy the atom bytecode)
86868 		                                     */
86869 		duk_uint32_t new_atom_start_captures;  /* re_ctx->captures at the start of the atom parsed in this loop */
86870 
86871 		duk_lexer_parse_re_token(&re_ctx->lex, &re_ctx->curr_token);
86872 
86873 		DUK_DD(DUK_DDPRINT("re token: %ld (num=%ld, char=%c)",
86874 		                   (long) re_ctx->curr_token.t,
86875 		                   (long) re_ctx->curr_token.num,
86876 		                   (re_ctx->curr_token.num >= 0x20 && re_ctx->curr_token.num <= 0x7e) ?
86877 		                   (int) re_ctx->curr_token.num : (int) '?'));
86878 
86879 		/* set by atom case clauses */
86880 		new_atom_start_offset = -1;
86881 		new_atom_char_length = -1;
86882 		new_atom_start_captures = re_ctx->captures;
86883 
86884 		switch (re_ctx->curr_token.t) {
86885 		case DUK_RETOK_DISJUNCTION: {
86886 			/*
86887 			 *  The handling here is a bit tricky.  If a previous '|' has been processed,
86888 			 *  we have a pending split1 and a pending jump (for a previous match).  These
86889 			 *  need to be back-patched carefully.  See docs for a detailed example.
86890 			 */
86891 
86892 			/* patch pending jump and split */
86893 			if (unpatched_disjunction_jump >= 0) {
86894 				duk_uint32_t offset;
86895 
86896 				DUK_ASSERT(unpatched_disjunction_split >= 0);
86897 				offset = (duk_uint32_t) unpatched_disjunction_jump;
86898 				offset += duk__insert_jump_offset(re_ctx,
86899 				                                  offset,
86900 				                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
86901 				/* offset is now target of the pending split (right after jump) */
86902 				duk__insert_jump_offset(re_ctx,
86903 				                        (duk_uint32_t) unpatched_disjunction_split,
86904 				                        (duk_int32_t) offset - unpatched_disjunction_split);
86905 			}
86906 
86907 			/* add a new pending split to the beginning of the entire disjunction */
86908 			(void) duk__insert_u32(re_ctx,
86909 			                       entry_offset,
86910 			                       DUK_REOP_SPLIT1);   /* prefer direct execution */
86911 			unpatched_disjunction_split = (duk_int32_t) (entry_offset + 1);   /* +1 for opcode */
86912 
86913 			/* add a new pending match jump for latest finished alternative */
86914 			duk__append_reop(re_ctx, DUK_REOP_JUMP);
86915 			unpatched_disjunction_jump = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
86916 
86917 			/* 'taint' result as complex */
86918 			res_charlen = -1;
86919 			break;
86920 		}
86921 		case DUK_RETOK_QUANTIFIER: {
86922 			if (atom_start_offset < 0) {
86923 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_NO_ATOM);
86924 				DUK_WO_NORETURN(return;);
86925 			}
86926 			if (re_ctx->curr_token.qmin > re_ctx->curr_token.qmax) {
86927 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_INVALID_QUANTIFIER_VALUES);
86928 				DUK_WO_NORETURN(return;);
86929 			}
86930 			if (atom_char_length >= 0) {
86931 				/*
86932 				 *  Simple atom
86933 				 *
86934 				 *  If atom_char_length is zero, we'll have unbounded execution time for e.g.
86935 				 *  /()*x/.exec('x').  We can't just skip the match because it might have some
86936 				 *  side effects (for instance, if we allowed captures in simple atoms, the
86937 				 *  capture needs to happen).  The simple solution below is to force the
86938 				 *  quantifier to match at most once, since the additional matches have no effect.
86939 				 *
86940 				 *  With a simple atom there can be no capture groups, so no captures need
86941 				 *  to be reset.
86942 				 */
86943 				duk_int32_t atom_code_length;
86944 				duk_uint32_t offset;
86945 				duk_uint32_t qmin, qmax;
86946 
86947 				qmin = re_ctx->curr_token.qmin;
86948 				qmax = re_ctx->curr_token.qmax;
86949 				if (atom_char_length == 0) {
86950 					/* qmin and qmax will be 0 or 1 */
86951 					if (qmin > 1) {
86952 						qmin = 1;
86953 					}
86954 					if (qmax > 1) {
86955 						qmax = 1;
86956 					}
86957 				}
86958 
86959 				duk__append_reop(re_ctx, DUK_REOP_MATCH);   /* complete 'sub atom' */
86960 				atom_code_length = (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (duk_size_t) atom_start_offset);
86961 
86962 				offset = (duk_uint32_t) atom_start_offset;
86963 				if (re_ctx->curr_token.greedy) {
86964 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQGREEDY);
86965 					offset += duk__insert_u32(re_ctx, offset, qmin);
86966 					offset += duk__insert_u32(re_ctx, offset, qmax);
86967 					offset += duk__insert_u32(re_ctx, offset, (duk_uint32_t) atom_char_length);
86968 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
86969 				} else {
86970 					offset += duk__insert_u32(re_ctx, offset, DUK_REOP_SQMINIMAL);
86971 					offset += duk__insert_u32(re_ctx, offset, qmin);
86972 					offset += duk__insert_u32(re_ctx, offset, qmax);
86973 					offset += duk__insert_jump_offset(re_ctx, offset, atom_code_length);
86974 				}
86975 				DUK_UNREF(offset);  /* silence scan-build warning */
86976 			} else {
86977 				/*
86978 				 *  Complex atom
86979 				 *
86980 				 *  The original code is used as a template, and removed at the end
86981 				 *  (this differs from the handling of simple quantifiers).
86982 				 *
86983 				 *  NOTE: there is no current solution for empty atoms in complex
86984 				 *  quantifiers.  This would need some sort of a 'progress' instruction.
86985 				 *
86986 				 *  XXX: impose limit on maximum result size, i.e. atom_code_len * atom_copies?
86987 				 */
86988 				duk_int32_t atom_code_length;
86989 				duk_uint32_t atom_copies;
86990 				duk_uint32_t tmp_qmin, tmp_qmax;
86991 
86992 				/* pre-check how many atom copies we're willing to make (atom_copies not needed below) */
86993 				atom_copies = (re_ctx->curr_token.qmax == DUK_RE_QUANTIFIER_INFINITE) ?
86994 				              re_ctx->curr_token.qmin : re_ctx->curr_token.qmax;
86995 				if (atom_copies > DUK_RE_MAX_ATOM_COPIES) {
86996 					DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_QUANTIFIER_TOO_MANY_COPIES);
86997 					DUK_WO_NORETURN(return;);
86998 				}
86999 
87000 				/* wipe the capture range made by the atom (if any) */
87001 				DUK_ASSERT(atom_start_captures <= re_ctx->captures);
87002 				if (atom_start_captures != re_ctx->captures) {
87003 					DUK_ASSERT(atom_start_captures < re_ctx->captures);
87004 					DUK_DDD(DUK_DDDPRINT("must wipe ]atom_start_captures,re_ctx->captures]: ]%ld,%ld]",
87005 					                     (long) atom_start_captures, (long) re_ctx->captures));
87006 
87007 					/* insert (DUK_REOP_WIPERANGE, start, count) in reverse order so the order ends up right */
87008 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (re_ctx->captures - atom_start_captures) * 2U);
87009 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, (atom_start_captures + 1) * 2);
87010 					duk__insert_u32(re_ctx, (duk_uint32_t) atom_start_offset, DUK_REOP_WIPERANGE);
87011 				} else {
87012 					DUK_DDD(DUK_DDDPRINT("no need to wipe captures: atom_start_captures == re_ctx->captures == %ld",
87013 					                     (long) atom_start_captures));
87014 				}
87015 
87016 				atom_code_length = (duk_int32_t) DUK__RE_BUFLEN(re_ctx) - atom_start_offset;
87017 
87018 				/* insert the required matches (qmin) by copying the atom */
87019 				tmp_qmin = re_ctx->curr_token.qmin;
87020 				tmp_qmax = re_ctx->curr_token.qmax;
87021 				while (tmp_qmin > 0) {
87022 					duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87023 					tmp_qmin--;
87024 					if (tmp_qmax != DUK_RE_QUANTIFIER_INFINITE) {
87025 						tmp_qmax--;
87026 					}
87027 				}
87028 				DUK_ASSERT(tmp_qmin == 0);
87029 
87030 				/* insert code for matching the remainder - infinite or finite */
87031 				if (tmp_qmax == DUK_RE_QUANTIFIER_INFINITE) {
87032 					/* reuse last emitted atom for remaining 'infinite' quantifier */
87033 
87034 					if (re_ctx->curr_token.qmin == 0) {
87035 						/* Special case: original qmin was zero so there is nothing
87036 						 * to repeat.  Emit an atom copy but jump over it here.
87037 						 */
87038 						duk__append_reop(re_ctx, DUK_REOP_JUMP);
87039 						duk__append_jump_offset(re_ctx, atom_code_length);
87040 						duk__append_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87041 					}
87042 					if (re_ctx->curr_token.greedy) {
87043 						duk__append_reop(re_ctx, DUK_REOP_SPLIT2);   /* prefer jump */
87044 					} else {
87045 						duk__append_reop(re_ctx, DUK_REOP_SPLIT1);   /* prefer direct */
87046 					}
87047 					duk__append_jump_offset(re_ctx, -atom_code_length - 1);  /* -1 for opcode */
87048 				} else {
87049 					/*
87050 					 *  The remaining matches are emitted as sequence of SPLITs and atom
87051 					 *  copies; the SPLITs skip the remaining copies and match the sequel.
87052 					 *  This sequence needs to be emitted starting from the last copy
87053 					 *  because the SPLITs are variable length due to the variable length
87054 					 *  skip offset.  This causes a lot of memory copying now.
87055 					 *
87056 					 *  Example structure (greedy, match maximum # atoms):
87057 					 *
87058 					 *      SPLIT1 LSEQ
87059 					 *      (atom)
87060 					 *      SPLIT1 LSEQ    ; <- the byte length of this instruction is needed
87061 					 *      (atom)         ; to encode the above SPLIT1 correctly
87062 					 *      ...
87063 					 *   LSEQ:
87064 					 */
87065 					duk_uint32_t offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87066 					while (tmp_qmax > 0) {
87067 						duk__insert_slice(re_ctx, offset, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87068 						if (re_ctx->curr_token.greedy) {
87069 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT1);   /* prefer direct */
87070 						} else {
87071 							duk__insert_u32(re_ctx, offset, DUK_REOP_SPLIT2);   /* prefer jump */
87072 						}
87073 						duk__insert_jump_offset(re_ctx,
87074 						                        offset + 1,   /* +1 for opcode */
87075 						                        (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87076 						tmp_qmax--;
87077 					}
87078 				}
87079 
87080 				/* remove the original 'template' atom */
87081 				duk__remove_slice(re_ctx, (duk_uint32_t) atom_start_offset, (duk_uint32_t) atom_code_length);
87082 			}
87083 
87084 			/* 'taint' result as complex */
87085 			res_charlen = -1;
87086 			break;
87087 		}
87088 		case DUK_RETOK_ASSERT_START: {
87089 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_START);
87090 			break;
87091 		}
87092 		case DUK_RETOK_ASSERT_END: {
87093 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_END);
87094 			break;
87095 		}
87096 		case DUK_RETOK_ASSERT_WORD_BOUNDARY: {
87097 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_WORD_BOUNDARY);
87098 			break;
87099 		}
87100 		case DUK_RETOK_ASSERT_NOT_WORD_BOUNDARY: {
87101 			duk__append_reop(re_ctx, DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
87102 			break;
87103 		}
87104 		case DUK_RETOK_ASSERT_START_POS_LOOKAHEAD:
87105 		case DUK_RETOK_ASSERT_START_NEG_LOOKAHEAD: {
87106 			duk_uint32_t offset;
87107 			duk_uint32_t opcode = (re_ctx->curr_token.t == DUK_RETOK_ASSERT_START_POS_LOOKAHEAD) ?
87108 			                      DUK_REOP_LOOKPOS : DUK_REOP_LOOKNEG;
87109 
87110 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);
87111 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87112 			duk__append_reop(re_ctx, DUK_REOP_MATCH);
87113 
87114 			(void) duk__insert_u32(re_ctx, offset, opcode);
87115 			(void) duk__insert_jump_offset(re_ctx,
87116 			                               offset + 1,   /* +1 for opcode */
87117 			                               (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - (offset + 1)));
87118 
87119 			/* 'taint' result as complex -- this is conservative,
87120 			 * as lookaheads do not backtrack.
87121 			 */
87122 			res_charlen = -1;
87123 			break;
87124 		}
87125 		case DUK_RETOK_ATOM_PERIOD: {
87126 			new_atom_char_length = 1;
87127 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87128 			duk__append_reop(re_ctx, DUK_REOP_PERIOD);
87129 			break;
87130 		}
87131 		case DUK_RETOK_ATOM_CHAR: {
87132 			/* Note: successive characters could be joined into string matches
87133 			 * but this is not trivial (consider e.g. '/xyz+/); see docs for
87134 			 * more discussion.
87135 			 *
87136 			 * No support for \u{H+} yet.  While only BMP Unicode escapes are
87137 			 * supported for RegExps at present, 'ch' may still be a non-BMP
87138 			 * codepoint if it is decoded straight from source text UTF-8.
87139 			 * There's no non-BMP support yet so this is handled simply by
87140 			 * matching the non-BMP character (which is custom behavior).
87141 			 */
87142 			duk_uint32_t ch;
87143 
87144 			new_atom_char_length = 1;
87145 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87146 			duk__append_reop(re_ctx, DUK_REOP_CHAR);
87147 			ch = re_ctx->curr_token.num;
87148 			if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
87149 				ch = (duk_uint32_t) duk_unicode_re_canonicalize_char(re_ctx->thr, (duk_codepoint_t) ch);
87150 			}
87151 			duk__append_u32(re_ctx, ch);
87152 			break;
87153 		}
87154 		case DUK_RETOK_ATOM_DIGIT:
87155 		case DUK_RETOK_ATOM_NOT_DIGIT:
87156 		case DUK_RETOK_ATOM_WHITE:
87157 		case DUK_RETOK_ATOM_NOT_WHITE:
87158 		case DUK_RETOK_ATOM_WORD_CHAR:
87159 		case DUK_RETOK_ATOM_NOT_WORD_CHAR: {
87160 			duk_small_uint_t re_op;
87161 			duk_small_uint_t idx;
87162 
87163 			new_atom_char_length = 1;
87164 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87165 
87166 			DUK_ASSERT((DUK_RETOK_ATOM_DIGIT & 0x01) != 0);
87167 			DUK_ASSERT((DUK_RETOK_ATOM_WHITE & 0x01) != 0);
87168 			DUK_ASSERT((DUK_RETOK_ATOM_WORD_CHAR & 0x01) != 0);
87169 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_DIGIT & 0x01) == 0);
87170 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WHITE & 0x01) == 0);
87171 			DUK_ASSERT((DUK_RETOK_ATOM_NOT_WORD_CHAR & 0x01) == 0);
87172 			re_op = (re_ctx->curr_token.t & 0x01) ? DUK_REOP_RANGES : DUK_REOP_INVRANGES;
87173 
87174 			DUK_ASSERT(DUK_RETOK_ATOM_WHITE == DUK_RETOK_ATOM_DIGIT + 2);
87175 			DUK_ASSERT(DUK_RETOK_ATOM_WORD_CHAR == DUK_RETOK_ATOM_DIGIT + 4);
87176 			idx = (duk_small_uint_t) ((re_ctx->curr_token.t - DUK_RETOK_ATOM_DIGIT) >> 1U);
87177 			DUK_ASSERT(idx <= 2U);  /* Assume continuous token numbers; also checks negative underflow. */
87178 
87179 			duk__append_range_atom_matcher(re_ctx, re_op, duk__re_range_lookup1[idx], duk__re_range_lookup2[idx]);
87180 			break;
87181 		}
87182 		case DUK_RETOK_ATOM_BACKREFERENCE: {
87183 			duk_uint32_t backref = (duk_uint32_t) re_ctx->curr_token.num;
87184 			if (backref > re_ctx->highest_backref) {
87185 				re_ctx->highest_backref = backref;
87186 			}
87187 			new_atom_char_length = -1;   /* mark as complex */
87188 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87189 			duk__append_reop(re_ctx, DUK_REOP_BACKREFERENCE);
87190 			duk__append_u32(re_ctx, backref);
87191 			break;
87192 		}
87193 		case DUK_RETOK_ATOM_START_CAPTURE_GROUP: {
87194 			duk_uint32_t cap;
87195 
87196 			new_atom_char_length = -1;   /* mark as complex (capture handling) */
87197 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87198 			cap = ++re_ctx->captures;
87199 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87200 			duk__append_u32(re_ctx, cap * 2);
87201 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);  /* retval (sub-atom char length) unused, tainted as complex above */
87202 			duk__append_reop(re_ctx, DUK_REOP_SAVE);
87203 			duk__append_u32(re_ctx, cap * 2 + 1);
87204 			break;
87205 		}
87206 		case DUK_RETOK_ATOM_START_NONCAPTURE_GROUP: {
87207 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87208 			duk__parse_disjunction(re_ctx, 0, &tmp_disj);
87209 			new_atom_char_length = tmp_disj.charlen;
87210 			break;
87211 		}
87212 		case DUK_RETOK_ATOM_START_CHARCLASS:
87213 		case DUK_RETOK_ATOM_START_CHARCLASS_INVERTED: {
87214 			/*
87215 			 *  Range parsing is done with a special lexer function which calls
87216 			 *  us for every range parsed.  This is different from how rest of
87217 			 *  the parsing works, but avoids a heavy, arbitrary size intermediate
87218 			 *  value type to hold the ranges.
87219 			 *
87220 			 *  Another complication is the handling of character ranges when
87221 			 *  case insensitive matching is used (see docs for discussion).
87222 			 *  The range handler callback given to the lexer takes care of this
87223 			 *  as well.
87224 			 *
87225 			 *  Note that duplicate ranges are not eliminated when parsing character
87226 			 *  classes, so that canonicalization of
87227 			 *
87228 			 *    [0-9a-fA-Fx-{]
87229 			 *
87230 			 *  creates the result (note the duplicate ranges):
87231 			 *
87232 			 *    [0-9A-FA-FX-Z{-{]
87233 			 *
87234 			 *  where [x-{] is split as a result of canonicalization.  The duplicate
87235 			 *  ranges are not a semantics issue: they work correctly.
87236 			 */
87237 
87238 			duk_uint32_t offset;
87239 
87240 			DUK_DD(DUK_DDPRINT("character class"));
87241 
87242 			/* insert ranges instruction, range count patched in later */
87243 			new_atom_char_length = 1;
87244 			new_atom_start_offset = (duk_int32_t) DUK__RE_BUFLEN(re_ctx);
87245 			duk__append_reop(re_ctx,
87246 			                 (re_ctx->curr_token.t == DUK_RETOK_ATOM_START_CHARCLASS) ?
87247 			                 DUK_REOP_RANGES : DUK_REOP_INVRANGES);
87248 			offset = (duk_uint32_t) DUK__RE_BUFLEN(re_ctx);    /* patch in range count later */
87249 
87250 			/* parse ranges until character class ends */
87251 			re_ctx->nranges = 0;    /* note: ctx-wide temporary */
87252 			duk_lexer_parse_re_ranges(&re_ctx->lex, duk__regexp_generate_ranges, (void *) re_ctx);
87253 
87254 			/* insert range count */
87255 			duk__insert_u32(re_ctx, offset, re_ctx->nranges);
87256 			break;
87257 		}
87258 		case DUK_RETOK_ATOM_END_GROUP: {
87259 			if (expect_eof) {
87260 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_CLOSING_PAREN);
87261 				DUK_WO_NORETURN(return;);
87262 			}
87263 			goto done;
87264 		}
87265 		case DUK_RETOK_EOF: {
87266 			if (!expect_eof) {
87267 				DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_END_OF_PATTERN);
87268 				DUK_WO_NORETURN(return;);
87269 			}
87270 			goto done;
87271 		}
87272 		default: {
87273 			DUK_ERROR_SYNTAX(re_ctx->thr, DUK_STR_UNEXPECTED_REGEXP_TOKEN);
87274 			DUK_WO_NORETURN(return;);
87275 		}
87276 		}
87277 
87278 		/* a complex (new) atom taints the result */
87279 		if (new_atom_start_offset >= 0) {
87280 			if (new_atom_char_length < 0) {
87281 				res_charlen = -1;
87282 			} else if (res_charlen >= 0) {
87283 				/* only advance if not tainted */
87284 				res_charlen += new_atom_char_length;
87285 			}
87286 		}
87287 
87288 		/* record previous atom info in case next token is a quantifier */
87289 		atom_start_offset = new_atom_start_offset;
87290 		atom_char_length = new_atom_char_length;
87291 		atom_start_captures = new_atom_start_captures;
87292 	}
87293 
87294  done:
87295 
87296 	/* finish up pending jump and split for last alternative */
87297 	if (unpatched_disjunction_jump >= 0) {
87298 		duk_uint32_t offset;
87299 
87300 		DUK_ASSERT(unpatched_disjunction_split >= 0);
87301 		offset = (duk_uint32_t) unpatched_disjunction_jump;
87302 		offset += duk__insert_jump_offset(re_ctx,
87303 		                                  offset,
87304 		                                  (duk_int32_t) (DUK__RE_BUFLEN(re_ctx) - offset));
87305 		/* offset is now target of the pending split (right after jump) */
87306 		duk__insert_jump_offset(re_ctx,
87307 		                        (duk_uint32_t) unpatched_disjunction_split,
87308 		                        (duk_int32_t) offset - unpatched_disjunction_split);
87309 	}
87310 
87311 #if 0
87312 	out_atom_info->end_captures = re_ctx->captures;
87313 #endif
87314 	out_atom_info->charlen = res_charlen;
87315 	DUK_DDD(DUK_DDDPRINT("parse disjunction finished: charlen=%ld",
87316 	                     (long) out_atom_info->charlen));
87317 
87318 	re_ctx->recursion_depth--;
87319 }
87320 
87321 /*
87322  *  Flags parsing (see E5 Section 15.10.4.1).
87323  */
87324 
87325 DUK_LOCAL duk_uint32_t duk__parse_regexp_flags(duk_hthread *thr, duk_hstring *h) {
87326 	const duk_uint8_t *p;
87327 	const duk_uint8_t *p_end;
87328 	duk_uint32_t flags = 0;
87329 
87330 	p = DUK_HSTRING_GET_DATA(h);
87331 	p_end = p + DUK_HSTRING_GET_BYTELEN(h);
87332 
87333 	/* Note: can be safely scanned as bytes (undecoded) */
87334 
87335 	while (p < p_end) {
87336 		duk_uint8_t c = *p++;
87337 		switch (c) {
87338 		case (duk_uint8_t) 'g': {
87339 			if (flags & DUK_RE_FLAG_GLOBAL) {
87340 				goto flags_error;
87341 			}
87342 			flags |= DUK_RE_FLAG_GLOBAL;
87343 			break;
87344 		}
87345 		case (duk_uint8_t) 'i': {
87346 			if (flags & DUK_RE_FLAG_IGNORE_CASE) {
87347 				goto flags_error;
87348 			}
87349 			flags |= DUK_RE_FLAG_IGNORE_CASE;
87350 			break;
87351 		}
87352 		case (duk_uint8_t) 'm': {
87353 			if (flags & DUK_RE_FLAG_MULTILINE) {
87354 				goto flags_error;
87355 			}
87356 			flags |= DUK_RE_FLAG_MULTILINE;
87357 			break;
87358 		}
87359 		default: {
87360 			goto flags_error;
87361 		}
87362 		}
87363 	}
87364 
87365 	return flags;
87366 
87367  flags_error:
87368 	DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_REGEXP_FLAGS);
87369 	DUK_WO_NORETURN(return 0U;);
87370 }
87371 
87372 /*
87373  *  Create escaped RegExp source (E5 Section 15.10.3).
87374  *
87375  *  The current approach is to special case the empty RegExp
87376  *  ('' -> '(?:)') and otherwise replace unescaped '/' characters
87377  *  with '\/' regardless of where they occur in the regexp.
87378  *
87379  *  Note that normalization does not seem to be necessary for
87380  *  RegExp literals (e.g. '/foo/') because to be acceptable as
87381  *  a RegExp literal, the text between forward slashes must
87382  *  already match the escaping requirements (e.g. must not contain
87383  *  unescaped forward slashes or be empty).  Escaping IS needed
87384  *  for expressions like 'new Regexp("...", "")' however.
87385  *  Currently, we re-escape in either case.
87386  *
87387  *  Also note that we process the source here in UTF-8 encoded
87388  *  form.  This is correct, because any non-ASCII characters are
87389  *  passed through without change.
87390  */
87391 
87392 DUK_LOCAL void duk__create_escaped_source(duk_hthread *thr, int idx_pattern) {
87393 	duk_hstring *h;
87394 	const duk_uint8_t *p;
87395 	duk_bufwriter_ctx bw_alloc;
87396 	duk_bufwriter_ctx *bw;
87397 	duk_uint8_t *q;
87398 	duk_size_t i, n;
87399 	duk_uint_fast8_t c_prev, c;
87400 
87401 	h = duk_known_hstring(thr, idx_pattern);
87402 	p = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h);
87403 	n = (duk_size_t) DUK_HSTRING_GET_BYTELEN(h);
87404 
87405 	if (n == 0) {
87406 		duk_push_literal(thr, "(?:)");
87407 		return;
87408 	}
87409 
87410 	bw = &bw_alloc;
87411 	DUK_BW_INIT_PUSHBUF(thr, bw, n);
87412 	q = DUK_BW_GET_PTR(thr, bw);
87413 
87414 	c_prev = (duk_uint_fast8_t) 0;
87415 
87416 	for (i = 0; i < n; i++) {
87417 		c = p[i];
87418 
87419 		q = DUK_BW_ENSURE_RAW(thr, bw, 2, q);
87420 
87421 		if (c == (duk_uint_fast8_t) '/' && c_prev != (duk_uint_fast8_t) '\\') {
87422 			/* Unescaped '/' ANYWHERE in the regexp (in disjunction,
87423 			 * inside a character class, ...) => same escape works.
87424 			 */
87425 			*q++ = DUK_ASC_BACKSLASH;
87426 		}
87427 		*q++ = (duk_uint8_t) c;
87428 
87429 		c_prev = c;
87430 	}
87431 
87432 	DUK_BW_SETPTR_AND_COMPACT(thr, bw, q);
87433 	(void) duk_buffer_to_string(thr, -1);  /* Safe if input is safe. */
87434 
87435 	/* [ ... escaped_source ] */
87436 }
87437 
87438 /*
87439  *  Exposed regexp compilation primitive.
87440  *
87441  *  Sets up a regexp compilation context, and calls duk__parse_disjunction() to do the
87442  *  actual parsing.  Handles generation of the compiled regexp header and the
87443  *  "boilerplate" capture of the matching substring (save 0 and 1).  Also does some
87444  *  global level regexp checks after recursive compilation has finished.
87445  *
87446  *  An escaped version of the regexp source, suitable for use as a RegExp instance
87447  *  'source' property (see E5 Section 15.10.3), is also left on the stack.
87448  *
87449  *  Input stack:  [ pattern flags ]
87450  *  Output stack: [ bytecode escaped_source ]  (both as strings)
87451  */
87452 
87453 DUK_INTERNAL void duk_regexp_compile(duk_hthread *thr) {
87454 	duk_re_compiler_ctx re_ctx;
87455 	duk_lexer_point lex_point;
87456 	duk_hstring *h_pattern;
87457 	duk_hstring *h_flags;
87458 	duk__re_disjunction_info ign_disj;
87459 
87460 	DUK_ASSERT(thr != NULL);
87461 
87462 	/*
87463 	 *  Args validation
87464 	 */
87465 
87466 	/* TypeError if fails */
87467 	h_pattern = duk_require_hstring_notsymbol(thr, -2);
87468 	h_flags = duk_require_hstring_notsymbol(thr, -1);
87469 
87470 	/*
87471 	 *  Create normalized 'source' property (E5 Section 15.10.3).
87472 	 */
87473 
87474 	/* [ ... pattern flags ] */
87475 
87476 	duk__create_escaped_source(thr, -2);
87477 
87478 	/* [ ... pattern flags escaped_source ] */
87479 
87480 	/*
87481 	 *  Init compilation context
87482 	 */
87483 
87484 	/* [ ... pattern flags escaped_source buffer ] */
87485 
87486 	duk_memzero(&re_ctx, sizeof(re_ctx));
87487 	DUK_LEXER_INITCTX(&re_ctx.lex);  /* duplicate zeroing, expect for (possible) NULL inits */
87488 	re_ctx.thr = thr;
87489 	re_ctx.lex.thr = thr;
87490 	re_ctx.lex.input = DUK_HSTRING_GET_DATA(h_pattern);
87491 	re_ctx.lex.input_length = DUK_HSTRING_GET_BYTELEN(h_pattern);
87492 	re_ctx.lex.token_limit = DUK_RE_COMPILE_TOKEN_LIMIT;
87493 	re_ctx.recursion_limit = DUK_USE_REGEXP_COMPILER_RECLIMIT;
87494 	re_ctx.re_flags = duk__parse_regexp_flags(thr, h_flags);
87495 
87496 	DUK_BW_INIT_PUSHBUF(thr, &re_ctx.bw, DUK__RE_INITIAL_BUFSIZE);
87497 
87498 	DUK_DD(DUK_DDPRINT("regexp compiler ctx initialized, flags=0x%08lx, recursion_limit=%ld",
87499 	                   (unsigned long) re_ctx.re_flags, (long) re_ctx.recursion_limit));
87500 
87501 	/*
87502 	 *  Init lexer
87503 	 */
87504 
87505 	lex_point.offset = 0;  /* expensive init, just want to fill window */
87506 	lex_point.line = 1;
87507 	DUK_LEXER_SETPOINT(&re_ctx.lex, &lex_point);
87508 
87509 	/*
87510 	 *  Compilation
87511 	 */
87512 
87513 	DUK_DD(DUK_DDPRINT("starting regexp compilation"));
87514 
87515 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
87516 	duk__append_7bit(&re_ctx, 0);
87517 	duk__parse_disjunction(&re_ctx, 1 /*expect_eof*/, &ign_disj);
87518 	duk__append_reop(&re_ctx, DUK_REOP_SAVE);
87519 	duk__append_7bit(&re_ctx, 1);
87520 	duk__append_reop(&re_ctx, DUK_REOP_MATCH);
87521 
87522 	/*
87523 	 *  Check for invalid backreferences; note that it is NOT an error
87524 	 *  to back-reference a capture group which has not yet been introduced
87525 	 *  in the pattern (as in /\1(foo)/); in fact, the backreference will
87526 	 *  always match!  It IS an error to back-reference a capture group
87527 	 *  which will never be introduced in the pattern.  Thus, we can check
87528 	 *  for such references only after parsing is complete.
87529 	 */
87530 
87531 	if (re_ctx.highest_backref > re_ctx.captures) {
87532 		DUK_ERROR_SYNTAX(thr, DUK_STR_INVALID_BACKREFS);
87533 		DUK_WO_NORETURN(return;);
87534 	}
87535 
87536 	/*
87537 	 *  Emit compiled regexp header: flags, ncaptures
87538 	 *  (insertion order inverted on purpose)
87539 	 */
87540 
87541 	duk__insert_u32(&re_ctx, 0, (re_ctx.captures + 1) * 2);
87542 	duk__insert_u32(&re_ctx, 0, re_ctx.re_flags);
87543 
87544 	/* [ ... pattern flags escaped_source buffer ] */
87545 
87546 	DUK_BW_COMPACT(thr, &re_ctx.bw);
87547 	(void) duk_buffer_to_string(thr, -1);  /* Safe because flags is at most 7 bit. */
87548 
87549 	/* [ ... pattern flags escaped_source bytecode ] */
87550 
87551 	/*
87552 	 *  Finalize stack
87553 	 */
87554 
87555 	duk_remove(thr, -4);     /* -> [ ... flags escaped_source bytecode ] */
87556 	duk_remove(thr, -3);     /* -> [ ... escaped_source bytecode ] */
87557 
87558 	DUK_DD(DUK_DDPRINT("regexp compilation successful, bytecode: %!T, escaped source: %!T",
87559 	                   (duk_tval *) duk_get_tval(thr, -1), (duk_tval *) duk_get_tval(thr, -2)));
87560 }
87561 
87562 /*
87563  *  Create a RegExp instance (E5 Section 15.10.7).
87564  *
87565  *  Note: the output stack left by duk_regexp_compile() is directly compatible
87566  *  with the input here.
87567  *
87568  *  Input stack:  [ escaped_source bytecode ]  (both as strings)
87569  *  Output stack: [ RegExp ]
87570  */
87571 
87572 DUK_INTERNAL void duk_regexp_create_instance(duk_hthread *thr) {
87573 	duk_hobject *h;
87574 
87575 	/* [ ... escaped_source bytecode ] */
87576 
87577 	duk_push_object(thr);
87578 	h = duk_known_hobject(thr, -1);
87579 	duk_insert(thr, -3);
87580 
87581 	/* [ ... regexp_object escaped_source bytecode ] */
87582 
87583 	DUK_HOBJECT_SET_CLASS_NUMBER(h, DUK_HOBJECT_CLASS_REGEXP);
87584 	DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h, thr->builtins[DUK_BIDX_REGEXP_PROTOTYPE]);
87585 
87586 	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_BYTECODE, DUK_PROPDESC_FLAGS_NONE);
87587 
87588 	/* [ ... regexp_object escaped_source ] */
87589 
87590 	/* In ES2015 .source, and the .global, .multiline, etc flags are
87591 	 * inherited getters.  Store the escaped source as an internal
87592 	 * property for the getter.
87593 	 */
87594 
87595 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_SOURCE, DUK_PROPDESC_FLAGS_NONE);
87596 
87597 	/* [ ... regexp_object ] */
87598 
87599 	duk_push_int(thr, 0);
87600 	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_LAST_INDEX, DUK_PROPDESC_FLAGS_W);
87601 
87602 	/* [ ... regexp_object ] */
87603 }
87604 
87605 #else  /* DUK_USE_REGEXP_SUPPORT */
87606 
87607 /* regexp support disabled */
87608 
87609 #endif  /* DUK_USE_REGEXP_SUPPORT */
87610 
87611 /* automatic undefs */
87612 #undef DUK__RE_BUFLEN
87613 #undef DUK__RE_INITIAL_BUFSIZE
87614 #line 1 "duk_regexp_executor.c"
87615 /*
87616  *  Regexp executor.
87617  *
87618  *  Safety: the ECMAScript executor should prevent user from reading and
87619  *  replacing regexp bytecode.  Even so, the executor must validate all
87620  *  memory accesses etc.  When an invalid access is detected (e.g. a 'save'
87621  *  opcode to invalid, unallocated index) it should fail with an internal
87622  *  error but not cause a segmentation fault.
87623  *
87624  *  Notes:
87625  *
87626  *    - Backtrack counts are limited to unsigned 32 bits but should
87627  *      technically be duk_size_t for strings longer than 4G chars.
87628  *      This also requires a regexp bytecode change.
87629  */
87630 
87631 /* #include duk_internal.h -> already included */
87632 
87633 #if defined(DUK_USE_REGEXP_SUPPORT)
87634 
87635 /*
87636  *  Helpers for UTF-8 handling
87637  *
87638  *  For bytecode readers the duk_uint32_t and duk_int32_t types are correct
87639  *  because they're used for more than just codepoints.
87640  */
87641 
87642 DUK_LOCAL duk_uint32_t duk__bc_get_u32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
87643 	return (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
87644 }
87645 
87646 DUK_LOCAL duk_int32_t duk__bc_get_i32(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **pc) {
87647 	duk_uint32_t t;
87648 
87649 	/* signed integer encoding needed to work with UTF-8 */
87650 	t = (duk_uint32_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, pc, re_ctx->bytecode, re_ctx->bytecode_end);
87651 	if (t & 1) {
87652 		return -((duk_int32_t) (t >> 1));
87653 	} else {
87654 		return (duk_int32_t) (t >> 1);
87655 	}
87656 }
87657 
87658 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) {
87659 	const duk_uint8_t *p;
87660 
87661 	/* Note: allow backtracking from p == ptr_end */
87662 	p = *ptr;
87663 	if (p < ptr_start || p > ptr_end) {
87664 		goto fail;
87665 	}
87666 
87667 	while (count > 0) {
87668 		for (;;) {
87669 			p--;
87670 			if (p < ptr_start) {
87671 				goto fail;
87672 			}
87673 			if ((*p & 0xc0) != 0x80) {
87674 				/* utf-8 continuation bytes have the form 10xx xxxx */
87675 				break;
87676 			}
87677 		}
87678 		count--;
87679 	}
87680 	*ptr = p;
87681 	return p;
87682 
87683  fail:
87684 	DUK_ERROR_INTERNAL(thr);
87685 	DUK_WO_NORETURN(return NULL;);
87686 }
87687 
87688 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) {
87689 	const duk_uint8_t *p;
87690 
87691 	p = *ptr;
87692 	if (p < ptr_start || p >= ptr_end) {
87693 		goto fail;
87694 	}
87695 
87696 	while (count > 0) {
87697 		for (;;) {
87698 			p++;
87699 
87700 			/* Note: if encoding ends by hitting end of input, we don't check that
87701 			 * the encoding is valid, we just assume it is.
87702 			 */
87703 			if (p >= ptr_end || ((*p & 0xc0) != 0x80)) {
87704 				/* utf-8 continuation bytes have the form 10xx xxxx */
87705 				break;
87706 			}
87707 		}
87708 		count--;
87709 	}
87710 
87711 	*ptr = p;
87712 	return p;
87713 
87714  fail:
87715 	DUK_ERROR_INTERNAL(thr);
87716 	DUK_WO_NORETURN(return NULL;);
87717 }
87718 
87719 /*
87720  *  Helpers for dealing with the input string
87721  */
87722 
87723 /* Get a (possibly canonicalized) input character from current sp.  The input
87724  * itself is never modified, and captures always record non-canonicalized
87725  * characters even in case-insensitive matching.  Return <0 if out of input.
87726  */
87727 DUK_LOCAL duk_codepoint_t duk__inp_get_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t **sp) {
87728 	duk_codepoint_t res;
87729 
87730 	if (*sp >= re_ctx->input_end) {
87731 		return -1;
87732 	}
87733 	res = (duk_codepoint_t) duk_unicode_decode_xutf8_checked(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end);
87734 	if (re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) {
87735 		res = duk_unicode_re_canonicalize_char(re_ctx->thr, res);
87736 	}
87737 	return res;
87738 }
87739 
87740 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) {
87741 	return duk__utf8_backtrack(re_ctx->thr, sp, re_ctx->input, re_ctx->input_end, count);
87742 }
87743 
87744 /* Backtrack utf-8 input and return a (possibly canonicalized) input character. */
87745 DUK_LOCAL duk_codepoint_t duk__inp_get_prev_cp(duk_re_matcher_ctx *re_ctx, const duk_uint8_t *sp) {
87746 	/* note: caller 'sp' is intentionally not updated here */
87747 	(void) duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) 1);
87748 	return duk__inp_get_cp(re_ctx, &sp);
87749 }
87750 
87751 /*
87752  *  Regexp recursive matching function.
87753  *
87754  *  Returns 'sp' on successful match (points to character after last matched one),
87755  *  NULL otherwise.
87756  *
87757  *  The C recursion depth limit check is only performed in this function, this
87758  *  suffices because the function is present in all true recursion required by
87759  *  regexp execution.
87760  */
87761 
87762 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) {
87763 	if (re_ctx->recursion_depth >= re_ctx->recursion_limit) {
87764 		DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_RECURSION_LIMIT);
87765 		DUK_WO_NORETURN(return NULL;);
87766 	}
87767 	re_ctx->recursion_depth++;
87768 
87769 	for (;;) {
87770 		duk_small_int_t op;
87771 
87772 		if (re_ctx->steps_count >= re_ctx->steps_limit) {
87773 			DUK_ERROR_RANGE(re_ctx->thr, DUK_STR_REGEXP_EXECUTOR_STEP_LIMIT);
87774 			DUK_WO_NORETURN(return NULL;);
87775 		}
87776 		re_ctx->steps_count++;
87777 
87778 		/* Opcodes are at most 7 bits now so they encode to one byte.  If this
87779 		 * were not the case or 'pc' is invalid here (due to a bug etc) we'll
87780 		 * still fail safely through the switch default case.
87781 		 */
87782 		DUK_ASSERT(pc[0] <= 0x7fU);
87783 #if 0
87784 		op = (duk_small_int_t) duk__bc_get_u32(re_ctx, &pc);
87785 #endif
87786 		op = *pc++;
87787 
87788 		DUK_DDD(DUK_DDDPRINT("match: rec=%ld, steps=%ld, pc (after op)=%ld, sp=%ld, op=%ld",
87789 		                     (long) re_ctx->recursion_depth,
87790 		                     (long) re_ctx->steps_count,
87791 		                     (long) (pc - re_ctx->bytecode),
87792 		                     (long) (sp - re_ctx->input),
87793 		                     (long) op));
87794 
87795 		switch (op) {
87796 		case DUK_REOP_MATCH: {
87797 			goto match;
87798 		}
87799 		case DUK_REOP_CHAR: {
87800 			/*
87801 			 *  Byte-based matching would be possible for case-sensitive
87802 			 *  matching but not for case-insensitive matching.  So, we
87803 			 *  match by decoding the input and bytecode character normally.
87804 			 *
87805 			 *  Bytecode characters are assumed to be already canonicalized.
87806 			 *  Input characters are canonicalized automatically by
87807 			 *  duk__inp_get_cp() if necessary.
87808 			 *
87809 			 *  There is no opcode for matching multiple characters.  The
87810 			 *  regexp compiler has trouble joining strings efficiently
87811 			 *  during compilation.  See doc/regexp.rst for more discussion.
87812 			 */
87813 			duk_codepoint_t c1, c2;
87814 
87815 			c1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87816 			DUK_ASSERT(!(re_ctx->re_flags & DUK_RE_FLAG_IGNORE_CASE) ||
87817 			           c1 == duk_unicode_re_canonicalize_char(re_ctx->thr, c1));  /* canonicalized by compiler */
87818 			c2 = duk__inp_get_cp(re_ctx, &sp);
87819 			/* No need to check for c2 < 0 (end of input): because c1 >= 0, it
87820 			 * will fail the match below automatically and cause goto fail.
87821 			 */
87822 #if 0
87823 			if (c2 < 0) {
87824 				goto fail;
87825 			}
87826 #endif
87827 			DUK_ASSERT(c1 >= 0);
87828 
87829 			DUK_DDD(DUK_DDDPRINT("char match, c1=%ld, c2=%ld", (long) c1, (long) c2));
87830 			if (c1 != c2) {
87831 				goto fail;
87832 			}
87833 			break;
87834 		}
87835 		case DUK_REOP_PERIOD: {
87836 			duk_codepoint_t c;
87837 
87838 			c = duk__inp_get_cp(re_ctx, &sp);
87839 			if (c < 0 || duk_unicode_is_line_terminator(c)) {
87840 				/* E5 Sections 15.10.2.8, 7.3 */
87841 				goto fail;
87842 			}
87843 			break;
87844 		}
87845 		case DUK_REOP_RANGES:
87846 		case DUK_REOP_INVRANGES: {
87847 			duk_uint32_t n;
87848 			duk_codepoint_t c;
87849 			duk_small_int_t match;
87850 
87851 			n = duk__bc_get_u32(re_ctx, &pc);
87852 			c = duk__inp_get_cp(re_ctx, &sp);
87853 			if (c < 0) {
87854 				goto fail;
87855 			}
87856 
87857 			match = 0;
87858 			while (n) {
87859 				duk_codepoint_t r1, r2;
87860 				r1 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87861 				r2 = (duk_codepoint_t) duk__bc_get_u32(re_ctx, &pc);
87862 				DUK_DDD(DUK_DDDPRINT("matching ranges/invranges, n=%ld, r1=%ld, r2=%ld, c=%ld",
87863 				                     (long) n, (long) r1, (long) r2, (long) c));
87864 				if (c >= r1 && c <= r2) {
87865 					/* Note: don't bail out early, we must read all the ranges from
87866 					 * bytecode.  Another option is to skip them efficiently after
87867 					 * breaking out of here.  Prefer smallest code.
87868 					 */
87869 					match = 1;
87870 				}
87871 				n--;
87872 			}
87873 
87874 			if (op == DUK_REOP_RANGES) {
87875 				if (!match) {
87876 					goto fail;
87877 				}
87878 			} else {
87879 				DUK_ASSERT(op == DUK_REOP_INVRANGES);
87880 				if (match) {
87881 					goto fail;
87882 				}
87883 			}
87884 			break;
87885 		}
87886 		case DUK_REOP_ASSERT_START: {
87887 			duk_codepoint_t c;
87888 
87889 			if (sp <= re_ctx->input) {
87890 				break;
87891 			}
87892 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
87893 				goto fail;
87894 			}
87895 			c = duk__inp_get_prev_cp(re_ctx, sp);
87896 			if (duk_unicode_is_line_terminator(c)) {
87897 				/* E5 Sections 15.10.2.8, 7.3 */
87898 				break;
87899 			}
87900 			goto fail;
87901 		}
87902 		case DUK_REOP_ASSERT_END: {
87903 			duk_codepoint_t c;
87904 			const duk_uint8_t *tmp_sp;
87905 
87906 			tmp_sp = sp;
87907 			c = duk__inp_get_cp(re_ctx, &tmp_sp);
87908 			if (c < 0) {
87909 				break;
87910 			}
87911 			if (!(re_ctx->re_flags & DUK_RE_FLAG_MULTILINE)) {
87912 				goto fail;
87913 			}
87914 			if (duk_unicode_is_line_terminator(c)) {
87915 				/* E5 Sections 15.10.2.8, 7.3 */
87916 				break;
87917 			}
87918 			goto fail;
87919 		}
87920 		case DUK_REOP_ASSERT_WORD_BOUNDARY:
87921 		case DUK_REOP_ASSERT_NOT_WORD_BOUNDARY: {
87922 			/*
87923 			 *  E5 Section 15.10.2.6.  The previous and current character
87924 			 *  should -not- be canonicalized as they are now.  However,
87925 			 *  canonicalization does not affect the result of IsWordChar()
87926 			 *  (which depends on Unicode characters never canonicalizing
87927 			 *  into ASCII characters) so this does not matter.
87928 			 */
87929 			duk_small_int_t w1, w2;
87930 
87931 			if (sp <= re_ctx->input) {
87932 				w1 = 0;  /* not a wordchar */
87933 			} else {
87934 				duk_codepoint_t c;
87935 				c = duk__inp_get_prev_cp(re_ctx, sp);
87936 				w1 = duk_unicode_re_is_wordchar(c);
87937 			}
87938 			if (sp >= re_ctx->input_end) {
87939 				w2 = 0;  /* not a wordchar */
87940 			} else {
87941 				const duk_uint8_t *tmp_sp = sp;  /* dummy so sp won't get updated */
87942 				duk_codepoint_t c;
87943 				c = duk__inp_get_cp(re_ctx, &tmp_sp);
87944 				w2 = duk_unicode_re_is_wordchar(c);
87945 			}
87946 
87947 			if (op == DUK_REOP_ASSERT_WORD_BOUNDARY) {
87948 				if (w1 == w2) {
87949 					goto fail;
87950 				}
87951 			} else {
87952 				DUK_ASSERT(op == DUK_REOP_ASSERT_NOT_WORD_BOUNDARY);
87953 				if (w1 != w2) {
87954 					goto fail;
87955 				}
87956 			}
87957 			break;
87958 		}
87959 		case DUK_REOP_JUMP: {
87960 			duk_int32_t skip;
87961 
87962 			skip = duk__bc_get_i32(re_ctx, &pc);
87963 			pc += skip;
87964 			break;
87965 		}
87966 		case DUK_REOP_SPLIT1: {
87967 			/* split1: prefer direct execution (no jump) */
87968 			const duk_uint8_t *sub_sp;
87969 			duk_int32_t skip;
87970 
87971 			skip = duk__bc_get_i32(re_ctx, &pc);
87972 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
87973 			if (sub_sp) {
87974 				sp = sub_sp;
87975 				goto match;
87976 			}
87977 			pc += skip;
87978 			break;
87979 		}
87980 		case DUK_REOP_SPLIT2: {
87981 			/* split2: prefer jump execution (not direct) */
87982 			const duk_uint8_t *sub_sp;
87983 			duk_int32_t skip;
87984 
87985 			skip = duk__bc_get_i32(re_ctx, &pc);
87986 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
87987 			if (sub_sp) {
87988 				sp = sub_sp;
87989 				goto match;
87990 			}
87991 			break;
87992 		}
87993 		case DUK_REOP_SQMINIMAL: {
87994 			duk_uint32_t q, qmin, qmax;
87995 			duk_int32_t skip;
87996 			const duk_uint8_t *sub_sp;
87997 
87998 			qmin = duk__bc_get_u32(re_ctx, &pc);
87999 			qmax = duk__bc_get_u32(re_ctx, &pc);
88000 			skip = duk__bc_get_i32(re_ctx, &pc);
88001 			DUK_DDD(DUK_DDDPRINT("minimal quantifier, qmin=%lu, qmax=%lu, skip=%ld",
88002 			                     (unsigned long) qmin, (unsigned long) qmax, (long) skip));
88003 
88004 			q = 0;
88005 			while (q <= qmax) {
88006 				if (q >= qmin) {
88007 					sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88008 					if (sub_sp) {
88009 						sp = sub_sp;
88010 						goto match;
88011 					}
88012 				}
88013 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88014 				if (!sub_sp) {
88015 					break;
88016 				}
88017 				sp = sub_sp;
88018 				q++;
88019 			}
88020 			goto fail;
88021 		}
88022 		case DUK_REOP_SQGREEDY: {
88023 			duk_uint32_t q, qmin, qmax, atomlen;
88024 			duk_int32_t skip;
88025 			const duk_uint8_t *sub_sp;
88026 
88027 			qmin = duk__bc_get_u32(re_ctx, &pc);
88028 			qmax = duk__bc_get_u32(re_ctx, &pc);
88029 			atomlen = duk__bc_get_u32(re_ctx, &pc);
88030 			skip = duk__bc_get_i32(re_ctx, &pc);
88031 			DUK_DDD(DUK_DDDPRINT("greedy quantifier, qmin=%lu, qmax=%lu, atomlen=%lu, skip=%ld",
88032 			                     (unsigned long) qmin, (unsigned long) qmax, (unsigned long) atomlen, (long) skip));
88033 
88034 			q = 0;
88035 			while (q < qmax) {
88036 				sub_sp = duk__match_regexp(re_ctx, pc, sp);
88037 				if (!sub_sp) {
88038 					break;
88039 				}
88040 				sp = sub_sp;
88041 				q++;
88042 			}
88043 			while (q >= qmin) {
88044 				sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88045 				if (sub_sp) {
88046 					sp = sub_sp;
88047 					goto match;
88048 				}
88049 				if (q == qmin) {
88050 					break;
88051 				}
88052 
88053 				/* Note: if atom were to contain e.g. captures, we would need to
88054 				 * re-match the atom to get correct captures.  Simply quantifiers
88055 				 * do not allow captures in their atom now, so this is not an issue.
88056 				 */
88057 
88058 				DUK_DDD(DUK_DDDPRINT("greedy quantifier, backtrack %ld characters (atomlen)",
88059 				                     (long) atomlen));
88060 				sp = duk__inp_backtrack(re_ctx, &sp, (duk_uint_fast32_t) atomlen);
88061 				q--;
88062 			}
88063 			goto fail;
88064 		}
88065 		case DUK_REOP_SAVE: {
88066 			duk_uint32_t idx;
88067 			const duk_uint8_t *old;
88068 			const duk_uint8_t *sub_sp;
88069 
88070 			idx = duk__bc_get_u32(re_ctx, &pc);
88071 			if (idx >= re_ctx->nsaved) {
88072 				/* idx is unsigned, < 0 check is not necessary */
88073 				DUK_D(DUK_DPRINT("internal error, regexp save index insane: idx=%ld", (long) idx));
88074 				goto internal_error;
88075 			}
88076 			old = re_ctx->saved[idx];
88077 			re_ctx->saved[idx] = sp;
88078 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88079 			if (sub_sp) {
88080 				sp = sub_sp;
88081 				goto match;
88082 			}
88083 			re_ctx->saved[idx] = old;
88084 			goto fail;
88085 		}
88086 		case DUK_REOP_WIPERANGE: {
88087 			/* Wipe capture range and save old values for backtracking.
88088 			 *
88089 			 * XXX: this typically happens with a relatively small idx_count.
88090 			 * It might be useful to handle cases where the count is small
88091 			 * (say <= 8) by saving the values in stack instead.  This would
88092 			 * reduce memory churn and improve performance, at the cost of a
88093 			 * slightly higher code footprint.
88094 			 */
88095 			duk_uint32_t idx_start, idx_count;
88096 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88097 			duk_uint32_t idx_end, idx;
88098 #endif
88099 			duk_uint8_t **range_save;
88100 			const duk_uint8_t *sub_sp;
88101 
88102 			idx_start = duk__bc_get_u32(re_ctx, &pc);
88103 			idx_count = duk__bc_get_u32(re_ctx, &pc);
88104 			DUK_DDD(DUK_DDDPRINT("wipe saved range: start=%ld, count=%ld -> [%ld,%ld] (captures [%ld,%ld])",
88105 			                     (long) idx_start, (long) idx_count,
88106 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88107 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88108 			if (idx_start + idx_count > re_ctx->nsaved || idx_count == 0) {
88109 				/* idx is unsigned, < 0 check is not necessary */
88110 				DUK_D(DUK_DPRINT("internal error, regexp wipe indices insane: idx_start=%ld, idx_count=%ld",
88111 				                 (long) idx_start, (long) idx_count));
88112 				goto internal_error;
88113 			}
88114 			DUK_ASSERT(idx_count > 0);
88115 
88116 			duk_require_stack(re_ctx->thr, 1);
88117 			range_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88118 			                                                           sizeof(duk_uint8_t *) * idx_count);
88119 			DUK_ASSERT(range_save != NULL);
88120 			duk_memcpy(range_save, re_ctx->saved + idx_start, sizeof(duk_uint8_t *) * idx_count);
88121 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88122 			idx_end = idx_start + idx_count;
88123 			for (idx = idx_start; idx < idx_end; idx++) {
88124 				re_ctx->saved[idx] = NULL;
88125 			}
88126 #else
88127 			duk_memzero((void *) (re_ctx->saved + idx_start), sizeof(duk_uint8_t *) * idx_count);
88128 #endif
88129 
88130 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88131 			if (sub_sp) {
88132 				/* match: keep wiped/resaved values */
88133 				DUK_DDD(DUK_DDDPRINT("match: keep wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88134 				                     (long) idx_start, (long) (idx_start + idx_count - 1),
88135 			                             (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88136 				duk_pop_unsafe(re_ctx->thr);
88137 				sp = sub_sp;
88138 				goto match;
88139 			}
88140 
88141 			/* fail: restore saves */
88142 			DUK_DDD(DUK_DDDPRINT("fail: restore wiped/resaved values [%ld,%ld] (captures [%ld,%ld])",
88143 			                     (long) idx_start, (long) (idx_start + idx_count - 1),
88144 			                     (long) (idx_start / 2), (long) ((idx_start + idx_count - 1) / 2)));
88145 			duk_memcpy((void *) (re_ctx->saved + idx_start),
88146 			           (const void *) range_save,
88147 			           sizeof(duk_uint8_t *) * idx_count);
88148 			duk_pop_unsafe(re_ctx->thr);
88149 			goto fail;
88150 		}
88151 		case DUK_REOP_LOOKPOS:
88152 		case DUK_REOP_LOOKNEG: {
88153 			/*
88154 			 *  Needs a save of multiple saved[] entries depending on what range
88155 			 *  may be overwritten.  Because the regexp parser does no such analysis,
88156 			 *  we currently save the entire saved array here.  Lookaheads are thus
88157 			 *  a bit expensive.  Note that the saved array is not needed for just
88158 			 *  the lookahead sub-match, but for the matching of the entire sequel.
88159 			 *
88160 			 *  The temporary save buffer is pushed on to the valstack to handle
88161 			 *  errors correctly.  Each lookahead causes a C recursion and pushes
88162 			 *  more stuff on the value stack.  If the C recursion limit is less
88163 			 *  than the value stack slack, there is no need to check the stack.
88164 			 *  We do so regardless, just in case.
88165 			 */
88166 
88167 			duk_int32_t skip;
88168 			duk_uint8_t **full_save;
88169 			const duk_uint8_t *sub_sp;
88170 
88171 			DUK_ASSERT(re_ctx->nsaved > 0);
88172 
88173 			duk_require_stack(re_ctx->thr, 1);
88174 			full_save = (duk_uint8_t **) duk_push_fixed_buffer_nozero(re_ctx->thr,
88175 			                                                          sizeof(duk_uint8_t *) * re_ctx->nsaved);
88176 			DUK_ASSERT(full_save != NULL);
88177 			duk_memcpy(full_save, re_ctx->saved, sizeof(duk_uint8_t *) * re_ctx->nsaved);
88178 
88179 			skip = duk__bc_get_i32(re_ctx, &pc);
88180 			sub_sp = duk__match_regexp(re_ctx, pc, sp);
88181 			if (op == DUK_REOP_LOOKPOS) {
88182 				if (!sub_sp) {
88183 					goto lookahead_fail;
88184 				}
88185 			} else {
88186 				if (sub_sp) {
88187 					goto lookahead_fail;
88188 				}
88189 			}
88190 			sub_sp = duk__match_regexp(re_ctx, pc + skip, sp);
88191 			if (sub_sp) {
88192 				/* match: keep saves */
88193 				duk_pop_unsafe(re_ctx->thr);
88194 				sp = sub_sp;
88195 				goto match;
88196 			}
88197 
88198 			/* fall through */
88199 
88200 		 lookahead_fail:
88201 			/* fail: restore saves */
88202 			duk_memcpy((void *) re_ctx->saved,
88203 			           (const void *) full_save,
88204 			           sizeof(duk_uint8_t *) * re_ctx->nsaved);
88205 			duk_pop_unsafe(re_ctx->thr);
88206 			goto fail;
88207 		}
88208 		case DUK_REOP_BACKREFERENCE: {
88209 			/*
88210 			 *  Byte matching for back-references would be OK in case-
88211 			 *  sensitive matching.  In case-insensitive matching we need
88212 			 *  to canonicalize characters, so back-reference matching needs
88213 			 *  to be done with codepoints instead.  So, we just decode
88214 			 *  everything normally here, too.
88215 			 *
88216 			 *  Note: back-reference index which is 0 or higher than
88217 			 *  NCapturingParens (= number of capturing parens in the
88218 			 *  -entire- regexp) is a compile time error.  However, a
88219 			 *  backreference referring to a valid capture which has
88220 			 *  not matched anything always succeeds!  See E5 Section
88221 			 *  15.10.2.9, step 5, sub-step 3.
88222 			 */
88223 			duk_uint32_t idx;
88224 			const duk_uint8_t *p;
88225 
88226 			idx = duk__bc_get_u32(re_ctx, &pc);
88227 			idx = idx << 1;  /* backref n -> saved indices [n*2, n*2+1] */
88228 			if (idx < 2 || idx + 1 >= re_ctx->nsaved) {
88229 				/* regexp compiler should catch these */
88230 				DUK_D(DUK_DPRINT("internal error, backreference index insane"));
88231 				goto internal_error;
88232 			}
88233 			if (!re_ctx->saved[idx] || !re_ctx->saved[idx+1]) {
88234 				/* capture is 'undefined', always matches! */
88235 				DUK_DDD(DUK_DDDPRINT("backreference: saved[%ld,%ld] not complete, always match",
88236 				                     (long) idx, (long) (idx + 1)));
88237 				break;
88238 			}
88239 			DUK_DDD(DUK_DDDPRINT("backreference: match saved[%ld,%ld]", (long) idx, (long) (idx + 1)));
88240 
88241 			p = re_ctx->saved[idx];
88242 			while (p < re_ctx->saved[idx+1]) {
88243 				duk_codepoint_t c1, c2;
88244 
88245 				/* Note: not necessary to check p against re_ctx->input_end:
88246 				 * the memory access is checked by duk__inp_get_cp(), while
88247 				 * valid compiled regexps cannot write a saved[] entry
88248 				 * which points to outside the string.
88249 				 */
88250 				c1 = duk__inp_get_cp(re_ctx, &p);
88251 				DUK_ASSERT(c1 >= 0);
88252 				c2 = duk__inp_get_cp(re_ctx, &sp);
88253 				/* No need for an explicit c2 < 0 check: because c1 >= 0,
88254 				 * the comparison will always fail if c2 < 0.
88255 				 */
88256 #if 0
88257 				if (c2 < 0) {
88258 					goto fail;
88259 				}
88260 #endif
88261 				if (c1 != c2) {
88262 					goto fail;
88263 				}
88264 			}
88265 			break;
88266 		}
88267 		default: {
88268 			DUK_D(DUK_DPRINT("internal error, regexp opcode error: %ld", (long) op));
88269 			goto internal_error;
88270 		}
88271 		}
88272 	}
88273 
88274  match:
88275 	re_ctx->recursion_depth--;
88276 	return sp;
88277 
88278  fail:
88279 	re_ctx->recursion_depth--;
88280 	return NULL;
88281 
88282  internal_error:
88283 	DUK_ERROR_INTERNAL(re_ctx->thr);
88284 	DUK_WO_NORETURN(return NULL;);
88285 }
88286 
88287 /*
88288  *  Exposed matcher function which provides the semantics of RegExp.prototype.exec().
88289  *
88290  *  RegExp.prototype.test() has the same semantics as exec() but does not return the
88291  *  result object (which contains the matching string and capture groups).  Currently
88292  *  there is no separate test() helper, so a temporary result object is created and
88293  *  discarded if test() is needed.  This is intentional, to save code space.
88294  *
88295  *  Input stack:  [ ... re_obj input ]
88296  *  Output stack: [ ... result ]
88297  */
88298 
88299 DUK_LOCAL void duk__regexp_match_helper(duk_hthread *thr, duk_small_int_t force_global) {
88300 	duk_re_matcher_ctx re_ctx;
88301 	duk_hobject *h_regexp;
88302 	duk_hstring *h_bytecode;
88303 	duk_hstring *h_input;
88304 	duk_uint8_t *p_buf;
88305 	const duk_uint8_t *pc;
88306 	const duk_uint8_t *sp;
88307 	duk_small_int_t match = 0;
88308 	duk_small_int_t global;
88309 	duk_uint_fast32_t i;
88310 	double d;
88311 	duk_uint32_t char_offset;
88312 
88313 	DUK_ASSERT(thr != NULL);
88314 
88315 	DUK_DD(DUK_DDPRINT("regexp match: regexp=%!T, input=%!T",
88316 	                   (duk_tval *) duk_get_tval(thr, -2),
88317 	                   (duk_tval *) duk_get_tval(thr, -1)));
88318 
88319 	/*
88320 	 *  Regexp instance check, bytecode check, input coercion.
88321 	 *
88322 	 *  See E5 Section 15.10.6.
88323 	 */
88324 
88325 	/* TypeError if wrong; class check, see E5 Section 15.10.6 */
88326 	h_regexp = duk_require_hobject_with_class(thr, -2, DUK_HOBJECT_CLASS_REGEXP);
88327 	DUK_ASSERT(h_regexp != NULL);
88328 	DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_regexp) == DUK_HOBJECT_CLASS_REGEXP);
88329 	DUK_UNREF(h_regexp);
88330 
88331 	h_input = duk_to_hstring(thr, -1);
88332 	DUK_ASSERT(h_input != NULL);
88333 
88334 	duk_get_prop_stridx_short(thr, -2, DUK_STRIDX_INT_BYTECODE);  /* [ ... re_obj input ] -> [ ... re_obj input bc ] */
88335 	h_bytecode = duk_require_hstring(thr, -1);  /* no regexp instance should exist without a non-configurable bytecode property */
88336 	DUK_ASSERT(h_bytecode != NULL);
88337 
88338 	/*
88339 	 *  Basic context initialization.
88340 	 *
88341 	 *  Some init values are read from the bytecode header
88342 	 *  whose format is (UTF-8 codepoints):
88343 	 *
88344 	 *    uint   flags
88345 	 *    uint   nsaved (even, 2n+2 where n = num captures)
88346 	 */
88347 
88348 	/* [ ... re_obj input bc ] */
88349 
88350 	duk_memzero(&re_ctx, sizeof(re_ctx));
88351 
88352 	re_ctx.thr = thr;
88353 	re_ctx.input = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_input);
88354 	re_ctx.input_end = re_ctx.input + DUK_HSTRING_GET_BYTELEN(h_input);
88355 	re_ctx.bytecode = (const duk_uint8_t *) DUK_HSTRING_GET_DATA(h_bytecode);
88356 	re_ctx.bytecode_end = re_ctx.bytecode + DUK_HSTRING_GET_BYTELEN(h_bytecode);
88357 	re_ctx.saved = NULL;
88358 	re_ctx.recursion_limit = DUK_USE_REGEXP_EXECUTOR_RECLIMIT;
88359 	re_ctx.steps_limit = DUK_RE_EXECUTE_STEPS_LIMIT;
88360 
88361 	/* read header */
88362 	pc = re_ctx.bytecode;
88363 	re_ctx.re_flags = duk__bc_get_u32(&re_ctx, &pc);
88364 	re_ctx.nsaved = duk__bc_get_u32(&re_ctx, &pc);
88365 	re_ctx.bytecode = pc;
88366 
88367 	DUK_ASSERT(DUK_RE_FLAG_GLOBAL < 0x10000UL);  /* must fit into duk_small_int_t */
88368 	global = (duk_small_int_t) (force_global | (duk_small_int_t) (re_ctx.re_flags & DUK_RE_FLAG_GLOBAL));
88369 
88370 	DUK_ASSERT(re_ctx.nsaved >= 2);
88371 	DUK_ASSERT((re_ctx.nsaved % 2) == 0);
88372 
88373 	p_buf = (duk_uint8_t *) duk_push_fixed_buffer(thr, sizeof(duk_uint8_t *) * re_ctx.nsaved);  /* rely on zeroing */
88374 	DUK_UNREF(p_buf);
88375 	re_ctx.saved = (const duk_uint8_t **) duk_get_buffer(thr, -1, NULL);
88376 	DUK_ASSERT(re_ctx.saved != NULL);
88377 
88378 	/* [ ... re_obj input bc saved_buf ] */
88379 
88380 #if defined(DUK_USE_EXPLICIT_NULL_INIT)
88381 	for (i = 0; i < re_ctx.nsaved; i++) {
88382 		re_ctx.saved[i] = (duk_uint8_t *) NULL;
88383 	}
88384 #elif defined(DUK_USE_ZERO_BUFFER_DATA)
88385 	/* buffer is automatically zeroed */
88386 #else
88387 	duk_memzero((void *) p_buf, sizeof(duk_uint8_t *) * re_ctx.nsaved);
88388 #endif
88389 
88390 	DUK_DDD(DUK_DDDPRINT("regexp ctx initialized, flags=0x%08lx, nsaved=%ld, recursion_limit=%ld, steps_limit=%ld",
88391 	                     (unsigned long) re_ctx.re_flags, (long) re_ctx.nsaved, (long) re_ctx.recursion_limit,
88392 	                     (long) re_ctx.steps_limit));
88393 
88394 	/*
88395 	 *  Get starting character offset for match, and initialize 'sp' based on it.
88396 	 *
88397 	 *  Note: lastIndex is non-configurable so it must be present (we check the
88398 	 *  internal class of the object above, so we know it is).  User code can set
88399 	 *  its value to an arbitrary (garbage) value though; E5 requires that lastIndex
88400 	 *  be coerced to a number before using.  The code below works even if the
88401 	 *  property is missing: the value will then be coerced to zero.
88402 	 *
88403 	 *  Note: lastIndex may be outside Uint32 range even after ToInteger() coercion.
88404 	 *  For instance, ToInteger(+Infinity) = +Infinity.  We track the match offset
88405 	 *  as an integer, but pre-check it to be inside the 32-bit range before the loop.
88406 	 *  If not, the check in E5 Section 15.10.6.2, step 9.a applies.
88407 	 */
88408 
88409 	/* XXX: lastIndex handling produces a lot of asm */
88410 
88411 	/* [ ... re_obj input bc saved_buf ] */
88412 
88413 	duk_get_prop_stridx_short(thr, -4, DUK_STRIDX_LAST_INDEX);  /* -> [ ... re_obj input bc saved_buf lastIndex ] */
88414 	(void) duk_to_int(thr, -1);  /* ToInteger(lastIndex) */
88415 	d = duk_get_number(thr, -1);  /* integer, but may be +/- Infinite, +/- zero (not NaN, though) */
88416 	duk_pop_nodecref_unsafe(thr);
88417 
88418 	if (global) {
88419 		if (d < 0.0 || d > (double) DUK_HSTRING_GET_CHARLEN(h_input)) {
88420 			/* match fail */
88421 			char_offset = 0;   /* not really necessary */
88422 			DUK_ASSERT(match == 0);
88423 			goto match_over;
88424 		}
88425 		char_offset = (duk_uint32_t) d;
88426 	} else {
88427 		/* lastIndex must be ignored for non-global regexps, but get the
88428 		 * value for (theoretical) side effects.  No side effects can
88429 		 * really occur, because lastIndex is a normal property and is
88430 		 * always non-configurable for RegExp instances.
88431 		 */
88432 		char_offset = (duk_uint32_t) 0;
88433 	}
88434 
88435 	DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
88436 	sp = re_ctx.input + duk_heap_strcache_offset_char2byte(thr, h_input, char_offset);
88437 
88438 	/*
88439 	 *  Match loop.
88440 	 *
88441 	 *  Try matching at different offsets until match found or input exhausted.
88442 	 */
88443 
88444 	/* [ ... re_obj input bc saved_buf ] */
88445 
88446 	DUK_ASSERT(match == 0);
88447 
88448 	for (;;) {
88449 		/* char offset in [0, h_input->clen] (both ends inclusive), checked before entry */
88450 		DUK_ASSERT_DISABLE(char_offset >= 0);
88451 		DUK_ASSERT(char_offset <= DUK_HSTRING_GET_CHARLEN(h_input));
88452 
88453 		/* Note: re_ctx.steps is intentionally not reset, it applies to the entire unanchored match */
88454 		DUK_ASSERT(re_ctx.recursion_depth == 0);
88455 
88456 		DUK_DDD(DUK_DDDPRINT("attempt match at char offset %ld; %p [%p,%p]",
88457 		                     (long) char_offset, (const void *) sp,
88458 		                     (const void *) re_ctx.input, (const void *) re_ctx.input_end));
88459 
88460 		/*
88461 		 *  Note:
88462 		 *
88463 		 *    - duk__match_regexp() is required not to longjmp() in ordinary "non-match"
88464 		 *      conditions; a longjmp() will terminate the entire matching process.
88465 		 *
88466 		 *    - Clearing saved[] is not necessary because backtracking does it
88467 		 *
88468 		 *    - Backtracking also rewinds re_ctx.recursion back to zero, unless an
88469 		 *      internal/limit error occurs (which causes a longjmp())
88470 		 *
88471 		 *    - If we supported anchored matches, we would break out here
88472 		 *      unconditionally; however, ECMAScript regexps don't have anchored
88473 		 *      matches.  It might make sense to implement a fast bail-out if
88474 		 *      the regexp begins with '^' and sp is not 0: currently we'll just
88475 		 *      run through the entire input string, trivially failing the match
88476 		 *      at every non-zero offset.
88477 		 */
88478 
88479 		if (duk__match_regexp(&re_ctx, re_ctx.bytecode, sp) != NULL) {
88480 			DUK_DDD(DUK_DDDPRINT("match at offset %ld", (long) char_offset));
88481 			match = 1;
88482 			break;
88483 		}
88484 
88485 		/* advance by one character (code point) and one char_offset */
88486 		char_offset++;
88487 		if (char_offset > DUK_HSTRING_GET_CHARLEN(h_input)) {
88488 			/*
88489 			 *  Note:
88490 			 *
88491 			 *    - Intentionally attempt (empty) match at char_offset == k_input->clen
88492 			 *
88493 			 *    - Negative char_offsets have been eliminated and char_offset is duk_uint32_t
88494 			 *      -> no need or use for a negative check
88495 			 */
88496 
88497 			DUK_DDD(DUK_DDDPRINT("no match after trying all sp offsets"));
88498 			break;
88499 		}
88500 
88501 		/* avoid calling at end of input, will DUK_ERROR (above check suffices to avoid this) */
88502 		(void) duk__utf8_advance(thr, &sp, re_ctx.input, re_ctx.input_end, (duk_uint_fast32_t) 1);
88503 	}
88504 
88505  match_over:
88506 
88507 	/*
88508 	 *  Matching complete, create result array or return a 'null'.  Update lastIndex
88509 	 *  if necessary.  See E5 Section 15.10.6.2.
88510 	 *
88511 	 *  Because lastIndex is a character (not byte) offset, we need the character
88512 	 *  length of the match which we conveniently get as a side effect of interning
88513 	 *  the matching substring (0th index of result array).
88514 	 *
88515 	 *  saved[0]         start pointer (~ byte offset) of current match
88516 	 *  saved[1]         end pointer (~ byte offset) of current match (exclusive)
88517 	 *  char_offset      start character offset of current match (-> .index of result)
88518 	 *  char_end_offset  end character offset (computed below)
88519 	 */
88520 
88521 	/* [ ... re_obj input bc saved_buf ] */
88522 
88523 	if (match) {
88524 #if defined(DUK_USE_ASSERTIONS)
88525 		duk_hobject *h_res;
88526 #endif
88527 		duk_uint32_t char_end_offset = 0;
88528 
88529 		DUK_DDD(DUK_DDDPRINT("regexp matches at char_offset %ld", (long) char_offset));
88530 
88531 		DUK_ASSERT(re_ctx.nsaved >= 2);        /* must have start and end */
88532 		DUK_ASSERT((re_ctx.nsaved % 2) == 0);  /* and even number */
88533 
88534 		/* XXX: Array size is known before and (2 * re_ctx.nsaved) but not taken
88535 		 * advantage of now.  The array is not compacted either, as regexp match
88536 		 * objects are usually short lived.
88537 		 */
88538 
88539 		duk_push_array(thr);
88540 
88541 #if defined(DUK_USE_ASSERTIONS)
88542 		h_res = duk_require_hobject(thr, -1);
88543 		DUK_ASSERT(DUK_HOBJECT_HAS_EXTENSIBLE(h_res));
88544 		DUK_ASSERT(DUK_HOBJECT_HAS_EXOTIC_ARRAY(h_res));
88545 		DUK_ASSERT(DUK_HOBJECT_GET_CLASS_NUMBER(h_res) == DUK_HOBJECT_CLASS_ARRAY);
88546 #endif
88547 
88548 		/* [ ... re_obj input bc saved_buf res_obj ] */
88549 
88550 		duk_push_u32(thr, char_offset);
88551 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INDEX);
88552 
88553 		duk_dup_m4(thr);
88554 		duk_xdef_prop_stridx_short_wec(thr, -2, DUK_STRIDX_INPUT);
88555 
88556 		for (i = 0; i < re_ctx.nsaved; i += 2) {
88557 			/* Captures which are undefined have NULL pointers and are returned
88558 			 * as 'undefined'.  The same is done when saved[] pointers are insane
88559 			 * (this should, of course, never happen in practice).
88560 			 */
88561 			if (re_ctx.saved[i] && re_ctx.saved[i + 1] && re_ctx.saved[i + 1] >= re_ctx.saved[i]) {
88562 				duk_push_lstring(thr,
88563 				                 (const char *) re_ctx.saved[i],
88564 				                 (duk_size_t) (re_ctx.saved[i+1] - re_ctx.saved[i]));
88565 				if (i == 0) {
88566 					/* Assumes that saved[0] and saved[1] are always
88567 					 * set by regexp bytecode (if not, char_end_offset
88568 					 * will be zero).  Also assumes clen reflects the
88569 					 * correct char length.
88570 					 */
88571 					char_end_offset = char_offset + (duk_uint32_t) duk_get_length(thr, -1);  /* add charlen */
88572 				}
88573 			} else {
88574 				duk_push_undefined(thr);
88575 			}
88576 
88577 			/* [ ... re_obj input bc saved_buf res_obj val ] */
88578 			duk_put_prop_index(thr, -2, (duk_uarridx_t) (i / 2));
88579 		}
88580 
88581 		/* [ ... re_obj input bc saved_buf res_obj ] */
88582 
88583 		/* NB: 'length' property is automatically updated by the array setup loop */
88584 
88585 		if (global) {
88586 			/* global regexp: lastIndex updated on match */
88587 			duk_push_u32(thr, char_end_offset);
88588 			duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
88589 		} else {
88590 			/* non-global regexp: lastIndex never updated on match */
88591 			;
88592 		}
88593 	} else {
88594 		/*
88595 		 *  No match, E5 Section 15.10.6.2, step 9.a.i - 9.a.ii apply, regardless
88596 		 *  of 'global' flag of the RegExp.  In particular, if lastIndex is invalid
88597 		 *  initially, it is reset to zero.
88598 		 */
88599 
88600 		DUK_DDD(DUK_DDDPRINT("regexp does not match"));
88601 
88602 		duk_push_null(thr);
88603 
88604 		/* [ ... re_obj input bc saved_buf res_obj ] */
88605 
88606 		duk_push_int(thr, 0);
88607 		duk_put_prop_stridx_short(thr, -6, DUK_STRIDX_LAST_INDEX);
88608 	}
88609 
88610 	/* [ ... re_obj input bc saved_buf res_obj ] */
88611 
88612 	duk_insert(thr, -5);
88613 
88614 	/* [ ... res_obj re_obj input bc saved_buf ] */
88615 
88616 	duk_pop_n_unsafe(thr, 4);
88617 
88618 	/* [ ... res_obj ] */
88619 
88620 	/* XXX: these last tricks are unnecessary if the function is made
88621 	 * a genuine native function.
88622 	 */
88623 }
88624 
88625 DUK_INTERNAL void duk_regexp_match(duk_hthread *thr) {
88626 	duk__regexp_match_helper(thr, 0 /*force_global*/);
88627 }
88628 
88629 /* This variant is needed by String.prototype.split(); it needs to perform
88630  * global-style matching on a cloned RegExp which is potentially non-global.
88631  */
88632 DUK_INTERNAL void duk_regexp_match_force_global(duk_hthread *thr) {
88633 	duk__regexp_match_helper(thr, 1 /*force_global*/);
88634 }
88635 
88636 #else  /* DUK_USE_REGEXP_SUPPORT */
88637 
88638 /* regexp support disabled */
88639 
88640 #endif  /* DUK_USE_REGEXP_SUPPORT */
88641 #line 1 "duk_selftest.c"
88642 /*
88643  *  Self tests to ensure execution environment is sane.  Intended to catch
88644  *  compiler/platform problems which cannot be detected at compile time.
88645  */
88646 
88647 /* #include duk_internal.h -> already included */
88648 
88649 #if defined(DUK_USE_SELF_TESTS)
88650 
88651 /*
88652  *  Unions and structs for self tests
88653  */
88654 
88655 typedef union {
88656 	double d;
88657 	duk_uint8_t x[8];
88658 } duk__test_double_union;
88659 
88660 /* Self test failed.  Expects a local variable 'error_count' to exist. */
88661 #define DUK__FAILED(msg)  do { \
88662 		DUK_D(DUK_DPRINT("self test failed: " #msg " at " DUK_FILE_MACRO ":" DUK_MACRO_STRINGIFY(DUK_LINE_MACRO))); \
88663 		error_count++; \
88664 	} while (0)
88665 
88666 #define DUK__DBLUNION_CMP_TRUE(a,b)  do { \
88667 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) != 0) { \
88668 			DUK__FAILED("double union compares false (expected true)"); \
88669 		} \
88670 	} while (0)
88671 
88672 #define DUK__DBLUNION_CMP_FALSE(a,b)  do { \
88673 		if (duk_memcmp((const void *) (a), (const void *) (b), sizeof(duk__test_double_union)) == 0) { \
88674 			DUK__FAILED("double union compares true (expected false)"); \
88675 		} \
88676 	} while (0)
88677 
88678 typedef union {
88679 	duk_uint32_t i;
88680 	duk_uint8_t x[8];
88681 } duk__test_u32_union;
88682 
88683 #if defined(DUK_USE_INTEGER_LE)
88684 #define DUK__U32_INIT(u, a, b, c, d) do { \
88685 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
88686 	} while (0)
88687 #elif defined(DUK_USE_INTEGER_ME)
88688 #error integer mixed endian not supported now
88689 #elif defined(DUK_USE_INTEGER_BE)
88690 #define DUK__U32_INIT(u, a, b, c, d) do { \
88691 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
88692 	} while (0)
88693 #else
88694 #error unknown integer endianness
88695 #endif
88696 
88697 #if defined(DUK_USE_DOUBLE_LE)
88698 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88699 		(u)->x[0] = (h); (u)->x[1] = (g); (u)->x[2] = (f); (u)->x[3] = (e); \
88700 		(u)->x[4] = (d); (u)->x[5] = (c); (u)->x[6] = (b); (u)->x[7] = (a); \
88701 	} while (0)
88702 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88703 	((u)->x[0] == (h) && (u)->x[1] == (g) && (u)->x[2] == (f) && (u)->x[3] == (e) && \
88704 	 (u)->x[4] == (d) && (u)->x[5] == (c) && (u)->x[6] == (b) && (u)->x[7] == (a))
88705 #elif defined(DUK_USE_DOUBLE_ME)
88706 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88707 		(u)->x[0] = (d); (u)->x[1] = (c); (u)->x[2] = (b); (u)->x[3] = (a); \
88708 		(u)->x[4] = (h); (u)->x[5] = (g); (u)->x[6] = (f); (u)->x[7] = (e); \
88709 	} while (0)
88710 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88711 	((u)->x[0] == (d) && (u)->x[1] == (c) && (u)->x[2] == (b) && (u)->x[3] == (a) && \
88712 	 (u)->x[4] == (h) && (u)->x[5] == (g) && (u)->x[6] == (f) && (u)->x[7] == (e))
88713 #elif defined(DUK_USE_DOUBLE_BE)
88714 #define DUK__DOUBLE_INIT(u, a, b, c, d, e, f, g, h) do { \
88715 		(u)->x[0] = (a); (u)->x[1] = (b); (u)->x[2] = (c); (u)->x[3] = (d); \
88716 		(u)->x[4] = (e); (u)->x[5] = (f); (u)->x[6] = (g); (u)->x[7] = (h); \
88717 	} while (0)
88718 #define DUK__DOUBLE_COMPARE(u, a, b, c, d, e, f, g, h) \
88719 	((u)->x[0] == (a) && (u)->x[1] == (b) && (u)->x[2] == (c) && (u)->x[3] == (d) && \
88720 	 (u)->x[4] == (e) && (u)->x[5] == (f) && (u)->x[6] == (g) && (u)->x[7] == (h))
88721 #else
88722 #error unknown double endianness
88723 #endif
88724 
88725 /*
88726  *  Various sanity checks for typing
88727  */
88728 
88729 DUK_LOCAL duk_uint_t duk__selftest_types(void) {
88730 	duk_uint_t error_count = 0;
88731 
88732 	if (!(sizeof(duk_int8_t) == 1 &&
88733 	      sizeof(duk_uint8_t) == 1 &&
88734 	      sizeof(duk_int16_t) == 2 &&
88735 	      sizeof(duk_uint16_t) == 2 &&
88736 	      sizeof(duk_int32_t) == 4 &&
88737 	      sizeof(duk_uint32_t) == 4)) {
88738 		DUK__FAILED("duk_(u)int{8,16,32}_t size");
88739 	}
88740 #if defined(DUK_USE_64BIT_OPS)
88741 	if (!(sizeof(duk_int64_t) == 8 &&
88742 	      sizeof(duk_uint64_t) == 8)) {
88743 		DUK__FAILED("duk_(u)int64_t size");
88744 	}
88745 #endif
88746 
88747 	if (!(sizeof(duk_size_t) >= sizeof(duk_uint_t))) {
88748 		/* Some internal code now assumes that all duk_uint_t values
88749 		 * can be expressed with a duk_size_t.
88750 		 */
88751 		DUK__FAILED("duk_size_t is smaller than duk_uint_t");
88752 	}
88753 	if (!(sizeof(duk_int_t) >= 4)) {
88754 		DUK__FAILED("duk_int_t is not 32 bits");
88755 	}
88756 
88757 	return error_count;
88758 }
88759 
88760 /*
88761  *  Packed tval sanity
88762  */
88763 
88764 DUK_LOCAL duk_uint_t duk__selftest_packed_tval(void) {
88765 	duk_uint_t error_count = 0;
88766 
88767 #if defined(DUK_USE_PACKED_TVAL)
88768 	if (sizeof(void *) > 4) {
88769 		DUK__FAILED("packed duk_tval in use but sizeof(void *) > 4");
88770 	}
88771 #endif
88772 
88773 	return error_count;
88774 }
88775 
88776 /*
88777  *  Two's complement arithmetic.
88778  */
88779 
88780 DUK_LOCAL duk_uint_t duk__selftest_twos_complement(void) {
88781 	duk_uint_t error_count = 0;
88782 	volatile int test;
88783 	test = -1;
88784 
88785 	/* Note that byte order doesn't affect this test: all bytes in
88786 	 * 'test' will be 0xFF for two's complement.
88787 	 */
88788 	if (((volatile duk_uint8_t *) &test)[0] != (duk_uint8_t) 0xff) {
88789 		DUK__FAILED("two's complement arithmetic");
88790 	}
88791 
88792 	return error_count;
88793 }
88794 
88795 /*
88796  *  Byte order.  Important to self check, because on some exotic platforms
88797  *  there is no actual detection but rather assumption based on platform
88798  *  defines.
88799  */
88800 
88801 DUK_LOCAL duk_uint_t duk__selftest_byte_order(void) {
88802 	duk_uint_t error_count = 0;
88803 	duk__test_u32_union u1;
88804 	duk__test_double_union u2;
88805 
88806 	/*
88807 	 *  >>> struct.pack('>d', 102030405060).encode('hex')
88808 	 *  '4237c17c6dc40000'
88809 	 */
88810 
88811 	DUK__U32_INIT(&u1, 0xde, 0xad, 0xbe, 0xef);
88812 	DUK__DOUBLE_INIT(&u2, 0x42, 0x37, 0xc1, 0x7c, 0x6d, 0xc4, 0x00, 0x00);
88813 
88814 	if (u1.i != (duk_uint32_t) 0xdeadbeefUL) {
88815 		DUK__FAILED("duk_uint32_t byte order");
88816 	}
88817 
88818 	if (u2.d != (double) 102030405060.0) {
88819 		DUK__FAILED("double byte order");
88820 	}
88821 
88822 	return error_count;
88823 }
88824 
88825 /*
88826  *  DUK_BSWAP macros
88827  */
88828 
88829 DUK_LOCAL duk_uint_t duk__selftest_bswap_macros(void) {
88830 	duk_uint_t error_count = 0;
88831 	duk_uint32_t x32;
88832 	duk_uint16_t x16;
88833 	duk_double_union du;
88834 	duk_double_t du_diff;
88835 
88836 	x16 = 0xbeefUL;
88837 	x16 = DUK_BSWAP16(x16);
88838 	if (x16 != (duk_uint16_t) 0xefbeUL) {
88839 		DUK__FAILED("DUK_BSWAP16");
88840 	}
88841 
88842 	x32 = 0xdeadbeefUL;
88843 	x32 = DUK_BSWAP32(x32);
88844 	if (x32 != (duk_uint32_t) 0xefbeaddeUL) {
88845 		DUK__FAILED("DUK_BSWAP32");
88846 	}
88847 
88848 	/* >>> struct.unpack('>d', '4000112233445566'.decode('hex'))
88849 	 * (2.008366013071895,)
88850 	 */
88851 
88852 	du.uc[0] = 0x40; du.uc[1] = 0x00; du.uc[2] = 0x11; du.uc[3] = 0x22;
88853 	du.uc[4] = 0x33; du.uc[5] = 0x44; du.uc[6] = 0x55; du.uc[7] = 0x66;
88854 	DUK_DBLUNION_DOUBLE_NTOH(&du);
88855 	du_diff = du.d - 2.008366013071895;
88856 #if 0
88857 	DUK_D(DUK_DPRINT("du_diff: %lg\n", (double) du_diff));
88858 #endif
88859 	if (du_diff > 1e-15) {
88860 		/* Allow very small lenience because some compilers won't parse
88861 		 * exact IEEE double constants (happened in matrix testing with
88862 		 * Linux gcc-4.8 -m32 at least).
88863 		 */
88864 #if 0
88865 		DUK_D(DUK_DPRINT("Result of DUK_DBLUNION_DOUBLE_NTOH: %02x %02x %02x %02x %02x %02x %02x %02x\n",
88866 		            (unsigned int) du.uc[0], (unsigned int) du.uc[1],
88867 		            (unsigned int) du.uc[2], (unsigned int) du.uc[3],
88868 		            (unsigned int) du.uc[4], (unsigned int) du.uc[5],
88869 		            (unsigned int) du.uc[6], (unsigned int) du.uc[7]));
88870 #endif
88871 		DUK__FAILED("DUK_DBLUNION_DOUBLE_NTOH");
88872 	}
88873 
88874 	return error_count;
88875 }
88876 
88877 /*
88878  *  Basic double / byte union memory layout.
88879  */
88880 
88881 DUK_LOCAL duk_uint_t duk__selftest_double_union_size(void) {
88882 	duk_uint_t error_count = 0;
88883 
88884 	if (sizeof(duk__test_double_union) != 8) {
88885 		DUK__FAILED("invalid union size");
88886 	}
88887 
88888 	return error_count;
88889 }
88890 
88891 /*
88892  *  Union aliasing, see misc/clang_aliasing.c.
88893  */
88894 
88895 DUK_LOCAL duk_uint_t duk__selftest_double_aliasing(void) {
88896 	/* This testcase fails when Emscripten-generated code runs on Firefox.
88897 	 * It's not an issue because the failure should only affect packed
88898 	 * duk_tval representation, which is not used with Emscripten.
88899 	 */
88900 #if defined(DUK_USE_PACKED_TVAL)
88901 	duk_uint_t error_count = 0;
88902 	duk__test_double_union a, b;
88903 
88904 	/* Test signaling NaN and alias assignment in all endianness combinations.
88905 	 */
88906 
88907 	/* little endian */
88908 	a.x[0] = 0x11; a.x[1] = 0x22; a.x[2] = 0x33; a.x[3] = 0x44;
88909 	a.x[4] = 0x00; a.x[5] = 0x00; a.x[6] = 0xf1; a.x[7] = 0xff;
88910 	b = a;
88911 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88912 
88913 	/* big endian */
88914 	a.x[0] = 0xff; a.x[1] = 0xf1; a.x[2] = 0x00; a.x[3] = 0x00;
88915 	a.x[4] = 0x44; a.x[5] = 0x33; a.x[6] = 0x22; a.x[7] = 0x11;
88916 	b = a;
88917 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88918 
88919 	/* mixed endian */
88920 	a.x[0] = 0x00; a.x[1] = 0x00; a.x[2] = 0xf1; a.x[3] = 0xff;
88921 	a.x[4] = 0x11; a.x[5] = 0x22; a.x[6] = 0x33; a.x[7] = 0x44;
88922 	b = a;
88923 	DUK__DBLUNION_CMP_TRUE(&a, &b);
88924 
88925 	return error_count;
88926 #else
88927 	DUK_D(DUK_DPRINT("skip double aliasing self test when duk_tval is not packed"));
88928 	return 0;
88929 #endif
88930 }
88931 
88932 /*
88933  *  Zero sign, see misc/tcc_zerosign2.c.
88934  */
88935 
88936 DUK_LOCAL duk_uint_t duk__selftest_double_zero_sign(void) {
88937 	duk_uint_t error_count = 0;
88938 	duk__test_double_union a, b;
88939 
88940 	a.d = 0.0;
88941 	b.d = -a.d;
88942 	DUK__DBLUNION_CMP_FALSE(&a, &b);
88943 
88944 	return error_count;
88945 }
88946 
88947 /*
88948  *  Rounding mode: Duktape assumes round-to-nearest, check that this is true.
88949  *  If we had C99 fenv.h we could check that fegetround() == FE_TONEAREST,
88950  *  but we don't want to rely on that header; and even if we did, it's good
88951  *  to ensure the rounding actually works.
88952  */
88953 
88954 DUK_LOCAL duk_uint_t duk__selftest_double_rounding(void) {
88955 	duk_uint_t error_count = 0;
88956 	duk__test_double_union a, b, c;
88957 
88958 #if 0
88959 	/* Include <fenv.h> and test manually; these trigger failures: */
88960 	fesetround(FE_UPWARD);
88961 	fesetround(FE_DOWNWARD);
88962 	fesetround(FE_TOWARDZERO);
88963 
88964 	/* This is the default and passes. */
88965 	fesetround(FE_TONEAREST);
88966 #endif
88967 
88968 	/* Rounding tests check that none of the other modes (round to
88969 	 * +Inf, round to -Inf, round to zero) can be active:
88970 	 * http://www.gnu.org/software/libc/manual/html_node/Rounding.html
88971 	 */
88972 
88973 	/* 1.0 + 2^(-53): result is midway between 1.0 and 1.0 + ulp.
88974 	 * Round to nearest: 1.0
88975 	 * Round to +Inf:    1.0 + ulp
88976 	 * Round to -Inf:    1.0
88977 	 * Round to zero:    1.0
88978 	 * => Correct result eliminates round to +Inf.
88979 	 */
88980 	DUK__DOUBLE_INIT(&a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
88981 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
88982 	duk_memset((void *) &c, 0, sizeof(c));
88983 	c.d = a.d + b.d;
88984 	if (!DUK__DOUBLE_COMPARE(&c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) {
88985 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
88986 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
88987 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
88988 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
88989 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
88990 		DUK__FAILED("invalid result from 1.0 + 0.5ulp");
88991 	}
88992 
88993 	/* (1.0 + ulp) + 2^(-53): result is midway between 1.0 + ulp and 1.0 + 2*ulp.
88994 	 * Round to nearest: 1.0 + 2*ulp (round to even mantissa)
88995 	 * Round to +Inf:    1.0 + 2*ulp
88996 	 * Round to -Inf:    1.0 + ulp
88997 	 * Round to zero:    1.0 + ulp
88998 	 * => Correct result eliminates round to -Inf and round to zero.
88999 	 */
89000 	DUK__DOUBLE_INIT(&a, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
89001 	DUK__DOUBLE_INIT(&b, 0x3c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
89002 	duk_memset((void *) &c, 0, sizeof(c));
89003 	c.d = a.d + b.d;
89004 	if (!DUK__DOUBLE_COMPARE(&c, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02)) {
89005 		DUK_D(DUK_DPRINT("broken result (native endiannesss): %02x %02x %02x %02x %02x %02x %02x %02x",
89006 		                 (unsigned int) c.x[0], (unsigned int) c.x[1],
89007 		                 (unsigned int) c.x[2], (unsigned int) c.x[3],
89008 		                 (unsigned int) c.x[4], (unsigned int) c.x[5],
89009 		                 (unsigned int) c.x[6], (unsigned int) c.x[7]));
89010 		DUK__FAILED("invalid result from (1.0 + ulp) + 0.5ulp");
89011 	}
89012 
89013 	/* Could do negative number testing too, but the tests above should
89014 	 * differentiate between IEEE 754 rounding modes.
89015 	 */
89016 	return error_count;
89017 }
89018 
89019 /*
89020  *  fmod(): often a portability issue in embedded or bare platform targets.
89021  *  Check for at least minimally correct behavior.  Unlike some other math
89022  *  functions (like cos()) Duktape relies on fmod() internally too.
89023  */
89024 
89025 DUK_LOCAL duk_uint_t duk__selftest_fmod(void) {
89026 	duk_uint_t error_count = 0;
89027 	duk__test_double_union u1, u2;
89028 	volatile duk_double_t t1, t2, t3;
89029 
89030 	/* fmod() with integer argument and exponent 2^32 is used by e.g.
89031 	 * ToUint32() and some Duktape internals.
89032 	 */
89033 	u1.d = DUK_FMOD(10.0, 4294967296.0);
89034 	u2.d = 10.0;
89035 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89036 
89037 	u1.d = DUK_FMOD(4294967306.0, 4294967296.0);
89038 	u2.d = 10.0;
89039 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89040 
89041 	u1.d = DUK_FMOD(73014444042.0, 4294967296.0);
89042 	u2.d = 10.0;
89043 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89044 
89045 	/* 52-bit integer split into two parts:
89046 	 * >>> 0x1fedcba9876543
89047 	 * 8987183256397123
89048 	 * >>> float(0x1fedcba9876543) / float(2**53)
89049 	 * 0.9977777777777778
89050 	 */
89051 	u1.d = DUK_FMOD(8987183256397123.0, 4294967296.0);
89052 	u2.d = (duk_double_t) 0xa9876543UL;
89053 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89054 	t1 = 8987183256397123.0;
89055 	t2 = 4294967296.0;
89056 	t3 = t1 / t2;
89057 	u1.d = DUK_FLOOR(t3);
89058 	u2.d = (duk_double_t) 0x1fedcbUL;
89059 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89060 
89061 	/* C99 behavior is for fmod() result sign to mathc argument sign. */
89062 	u1.d = DUK_FMOD(-10.0, 4294967296.0);
89063 	u2.d = -10.0;
89064 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89065 
89066 	u1.d = DUK_FMOD(-4294967306.0, 4294967296.0);
89067 	u2.d = -10.0;
89068 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89069 
89070 	u1.d = DUK_FMOD(-73014444042.0, 4294967296.0);
89071 	u2.d = -10.0;
89072 	DUK__DBLUNION_CMP_TRUE(&u1, &u2);
89073 
89074 	return error_count;
89075 }
89076 
89077 /*
89078  *  Struct size/alignment if platform requires it
89079  *
89080  *  There are some compiler specific struct padding pragmas etc in use, this
89081  *  selftest ensures they're correctly detected and used.
89082  */
89083 
89084 DUK_LOCAL duk_uint_t duk__selftest_struct_align(void) {
89085 	duk_uint_t error_count = 0;
89086 
89087 #if (DUK_USE_ALIGN_BY == 4)
89088 	if ((sizeof(duk_hbuffer_fixed) % 4) != 0) {
89089 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 4");
89090 	}
89091 #elif (DUK_USE_ALIGN_BY == 8)
89092 	if ((sizeof(duk_hbuffer_fixed) % 8) != 0) {
89093 		DUK__FAILED("sizeof(duk_hbuffer_fixed) not aligned to 8");
89094 	}
89095 #elif (DUK_USE_ALIGN_BY == 1)
89096 	/* no check */
89097 #else
89098 #error invalid DUK_USE_ALIGN_BY
89099 #endif
89100 	return error_count;
89101 }
89102 
89103 /*
89104  *  64-bit arithmetic
89105  *
89106  *  There are some platforms/compilers where 64-bit types are available
89107  *  but don't work correctly.  Test for known cases.
89108  */
89109 
89110 DUK_LOCAL duk_uint_t duk__selftest_64bit_arithmetic(void) {
89111 	duk_uint_t error_count = 0;
89112 #if defined(DUK_USE_64BIT_OPS)
89113 	volatile duk_int64_t i;
89114 	volatile duk_double_t d;
89115 
89116 	/* Catch a double-to-int64 cast issue encountered in practice. */
89117 	d = 2147483648.0;
89118 	i = (duk_int64_t) d;
89119 	if (i != DUK_I64_CONSTANT(0x80000000)) {
89120 		DUK__FAILED("casting 2147483648.0 to duk_int64_t failed");
89121 	}
89122 #else
89123 	/* nop */
89124 #endif
89125 	return error_count;
89126 }
89127 
89128 /*
89129  *  Casting
89130  */
89131 
89132 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_small_uint(void) {
89133 	/*
89134 	 *  https://github.com/svaarala/duktape/issues/127#issuecomment-77863473
89135 	 */
89136 
89137 	duk_uint_t error_count = 0;
89138 
89139 	duk_double_t d1, d2;
89140 	duk_small_uint_t u;
89141 
89142 	duk_double_t d1v, d2v;
89143 	duk_small_uint_t uv;
89144 
89145 	/* Test without volatiles */
89146 
89147 	d1 = 1.0;
89148 	u = (duk_small_uint_t) d1;
89149 	d2 = (duk_double_t) u;
89150 
89151 	if (!(d1 == 1.0 && u == 1 && d2 == 1.0 && d1 == d2)) {
89152 		DUK__FAILED("double to duk_small_uint_t cast failed");
89153 	}
89154 
89155 	/* Same test with volatiles */
89156 
89157 	d1v = 1.0;
89158 	uv = (duk_small_uint_t) d1v;
89159 	d2v = (duk_double_t) uv;
89160 
89161 	if (!(d1v == 1.0 && uv == 1 && d2v == 1.0 && d1v == d2v)) {
89162 		DUK__FAILED("double to duk_small_uint_t cast failed");
89163 	}
89164 
89165 	return error_count;
89166 }
89167 
89168 DUK_LOCAL duk_uint_t duk__selftest_cast_double_to_uint32(void) {
89169 	/*
89170 	 *  This test fails on an exotic ARM target; double-to-uint
89171 	 *  cast is incorrectly clamped to -signed- int highest value.
89172 	 *
89173 	 *  https://github.com/svaarala/duktape/issues/336
89174 	 */
89175 
89176 	duk_uint_t error_count = 0;
89177 	duk_double_t dv;
89178 	duk_uint32_t uv;
89179 
89180 	dv = 3735928559.0;  /* 0xdeadbeef in decimal */
89181 	uv = (duk_uint32_t) dv;
89182 
89183 	if (uv != 0xdeadbeefUL) {
89184 		DUK__FAILED("double to duk_uint32_t cast failed");
89185 	}
89186 
89187 	return error_count;
89188 }
89189 
89190 /*
89191  *  Minimal test of user supplied allocation functions
89192  *
89193  *    - Basic alloc + realloc + free cycle
89194  *
89195  *    - Realloc to significantly larger size to (hopefully) trigger a
89196  *      relocation and check that relocation copying works
89197  */
89198 
89199 DUK_LOCAL duk_uint_t duk__selftest_alloc_funcs(duk_alloc_function alloc_func,
89200                                                duk_realloc_function realloc_func,
89201                                                duk_free_function free_func,
89202                                                void *udata) {
89203 	duk_uint_t error_count = 0;
89204 	void *ptr;
89205 	void *new_ptr;
89206 	duk_small_int_t i, j;
89207 	unsigned char x;
89208 
89209 	if (alloc_func == NULL || realloc_func == NULL || free_func == NULL) {
89210 		return 0;
89211 	}
89212 
89213 	for (i = 1; i <= 256; i++) {
89214 		ptr = alloc_func(udata, (duk_size_t) i);
89215 		if (ptr == NULL) {
89216 			DUK_D(DUK_DPRINT("alloc failed, ignore"));
89217 			continue;  /* alloc failed, ignore */
89218 		}
89219 		for (j = 0; j < i; j++) {
89220 			((unsigned char *) ptr)[j] = (unsigned char) (0x80 + j);
89221 		}
89222 		new_ptr = realloc_func(udata, ptr, 1024);
89223 		if (new_ptr == NULL) {
89224 			DUK_D(DUK_DPRINT("realloc failed, ignore"));
89225 			free_func(udata, ptr);
89226 			continue;  /* realloc failed, ignore */
89227 		}
89228 		ptr = new_ptr;
89229 		for (j = 0; j < i; j++) {
89230 			x = ((unsigned char *) ptr)[j];
89231 			if (x != (unsigned char) (0x80 + j)) {
89232 				DUK_D(DUK_DPRINT("byte at index %ld doesn't match after realloc: %02lx",
89233 				                 (long) j, (unsigned long) x));
89234 				DUK__FAILED("byte compare after realloc");
89235 				break;
89236 			}
89237 		}
89238 		free_func(udata, ptr);
89239 	}
89240 
89241 	return error_count;
89242 }
89243 
89244 /*
89245  *  Self test main
89246  */
89247 
89248 DUK_INTERNAL duk_uint_t duk_selftest_run_tests(duk_alloc_function alloc_func,
89249                                                duk_realloc_function realloc_func,
89250                                                duk_free_function free_func,
89251                                                void *udata) {
89252 	duk_uint_t error_count = 0;
89253 
89254 	DUK_D(DUK_DPRINT("self test starting"));
89255 
89256 	error_count += duk__selftest_types();
89257 	error_count += duk__selftest_packed_tval();
89258 	error_count += duk__selftest_twos_complement();
89259 	error_count += duk__selftest_byte_order();
89260 	error_count += duk__selftest_bswap_macros();
89261 	error_count += duk__selftest_double_union_size();
89262 	error_count += duk__selftest_double_aliasing();
89263 	error_count += duk__selftest_double_zero_sign();
89264 	error_count += duk__selftest_double_rounding();
89265 	error_count += duk__selftest_fmod();
89266 	error_count += duk__selftest_struct_align();
89267 	error_count += duk__selftest_64bit_arithmetic();
89268 	error_count += duk__selftest_cast_double_to_small_uint();
89269 	error_count += duk__selftest_cast_double_to_uint32();
89270 	error_count += duk__selftest_alloc_funcs(alloc_func, realloc_func, free_func, udata);
89271 
89272 	DUK_D(DUK_DPRINT("self test complete, total error count: %ld", (long) error_count));
89273 
89274 	return error_count;
89275 }
89276 
89277 #endif  /* DUK_USE_SELF_TESTS */
89278 
89279 /* automatic undefs */
89280 #undef DUK__DBLUNION_CMP_FALSE
89281 #undef DUK__DBLUNION_CMP_TRUE
89282 #undef DUK__DOUBLE_COMPARE
89283 #undef DUK__DOUBLE_INIT
89284 #undef DUK__FAILED
89285 #undef DUK__U32_INIT
89286 /* #include duk_internal.h -> already included */
89287 #line 2 "duk_tval.c"
89288 
89289 #if defined(DUK_USE_FASTINT)
89290 
89291 /*
89292  *  Manually optimized double-to-fastint downgrade check.
89293  *
89294  *  This check has a large impact on performance, especially for fastint
89295  *  slow paths, so must be changed carefully.  The code should probably be
89296  *  optimized for the case where the result does not fit into a fastint,
89297  *  to minimize the penalty for "slow path code" dealing with fractions etc.
89298  *
89299  *  At least on one tested soft float ARM platform double-to-int64 coercion
89300  *  is very slow (and sometimes produces incorrect results, see self tests).
89301  *  This algorithm combines a fastint compatibility check and extracting the
89302  *  integer value from an IEEE double for setting the tagged fastint.  For
89303  *  other platforms a more naive approach might be better.
89304  *
89305  *  See doc/fastint.rst for details.
89306  */
89307 
89308 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
89309 	duk_double_union du;
89310 	duk_int64_t i;
89311 	duk_small_int_t expt;
89312 	duk_small_int_t shift;
89313 
89314 	/* XXX: optimize for packed duk_tval directly? */
89315 
89316 	du.d = x;
89317 	i = (duk_int64_t) DUK_DBLUNION_GET_INT64(&du);
89318 	expt = (duk_small_int_t) ((i >> 52) & 0x07ff);
89319 	shift = expt - 1023;
89320 
89321 	if (shift >= 0 && shift <= 46) {  /* exponents 1023 to 1069 */
89322 		duk_int64_t t;
89323 
89324 		if (((DUK_I64_CONSTANT(0x000fffffffffffff) >> shift) & i) == 0) {
89325 			t = i | DUK_I64_CONSTANT(0x0010000000000000);  /* implicit leading one */
89326 			t = t & DUK_I64_CONSTANT(0x001fffffffffffff);
89327 			t = t >> (52 - shift);
89328 			if (i < 0) {
89329 				t = -t;
89330 			}
89331 			DUK_TVAL_SET_FASTINT(tv, t);
89332 			return;
89333 		}
89334 	} else if (shift == -1023) {  /* exponent 0 */
89335 		if (i >= 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
89336 			/* Note: reject negative zero. */
89337 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) 0);
89338 			return;
89339 		}
89340 	} else if (shift == 47) {  /* exponent 1070 */
89341 		if (i < 0 && (i & DUK_I64_CONSTANT(0x000fffffffffffff)) == 0) {
89342 			DUK_TVAL_SET_FASTINT(tv, (duk_int64_t) DUK_FASTINT_MIN);
89343 			return;
89344 		}
89345 	}
89346 
89347 	DUK_TVAL_SET_DOUBLE(tv, x);
89348 	return;
89349 }
89350 
89351 DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
89352 	duk_tval_set_number_chkfast_fast(tv, x);
89353 }
89354 
89355 /*
89356  *  Manually optimized number-to-double conversion
89357  */
89358 
89359 #if defined(DUK_USE_FASTINT) && defined(DUK_USE_PACKED_TVAL)
89360 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_packed(duk_tval *tv) {
89361 	duk_double_union du;
89362 	duk_uint64_t t;
89363 
89364 	t = (duk_uint64_t) DUK_DBLUNION_GET_UINT64(tv);
89365 	if ((t >> 48) != DUK_TAG_FASTINT) {
89366 		return tv->d;
89367 	} else if (t & DUK_U64_CONSTANT(0x0000800000000000)) {
89368 		t = (duk_uint64_t) (-((duk_int64_t) t));  /* avoid unary minus on unsigned */
89369 		t = t & DUK_U64_CONSTANT(0x0000ffffffffffff);  /* negative */
89370 		t |= DUK_U64_CONSTANT(0xc330000000000000);
89371 		DUK_DBLUNION_SET_UINT64(&du, t);
89372 		return du.d + 4503599627370496.0;  /* 1 << 52 */
89373 	} else if (t != 0) {
89374 		t &= DUK_U64_CONSTANT(0x0000ffffffffffff);  /* positive */
89375 		t |= DUK_U64_CONSTANT(0x4330000000000000);
89376 		DUK_DBLUNION_SET_UINT64(&du, t);
89377 		return du.d - 4503599627370496.0;  /* 1 << 52 */
89378 	} else {
89379 		return 0.0;  /* zero */
89380 	}
89381 }
89382 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89383 
89384 #if 0  /* unused */
89385 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
89386 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked(duk_tval *tv) {
89387 	duk_double_union du;
89388 	duk_uint64_t t;
89389 
89390 	DUK_ASSERT(tv->t == DUK_TAG_NUMBER || tv->t == DUK_TAG_FASTINT);
89391 
89392 	if (tv->t == DUK_TAG_FASTINT) {
89393 		if (tv->v.fi >= 0) {
89394 			t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
89395 			DUK_DBLUNION_SET_UINT64(&du, t);
89396 			return du.d - 4503599627370496.0;  /* 1 << 52 */
89397 		} else {
89398 			t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
89399 			DUK_DBLUNION_SET_UINT64(&du, t);
89400 			return du.d + 4503599627370496.0;  /* 1 << 52 */
89401 		}
89402 	} else {
89403 		return tv->v.d;
89404 	}
89405 }
89406 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89407 #endif  /* 0 */
89408 
89409 #if defined(DUK_USE_FASTINT) && !defined(DUK_USE_PACKED_TVAL)
89410 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv) {
89411 	duk_double_union du;
89412 	duk_uint64_t t;
89413 
89414 	DUK_ASSERT(tv->t == DUK_TAG_FASTINT);
89415 
89416 	if (tv->v.fi >= 0) {
89417 		t = DUK_U64_CONSTANT(0x4330000000000000) | (duk_uint64_t) tv->v.fi;
89418 		DUK_DBLUNION_SET_UINT64(&du, t);
89419 		return du.d - 4503599627370496.0;  /* 1 << 52 */
89420 	} else {
89421 		t = DUK_U64_CONSTANT(0xc330000000000000) | (duk_uint64_t) (-tv->v.fi);
89422 		DUK_DBLUNION_SET_UINT64(&du, t);
89423 		return du.d + 4503599627370496.0;  /* 1 << 52 */
89424 	}
89425 }
89426 #endif  /* DUK_USE_FASTINT && DUK_USE_PACKED_TVAL */
89427 
89428 #endif  /* DUK_USE_FASTINT */
89429 #line 1 "duk_unicode_tables.c"
89430 /*
89431  *  Unicode support tables automatically generated during build.
89432  */
89433 
89434 /* #include duk_internal.h -> already included */
89435 
89436 /*
89437  *  Unicode tables containing ranges of Unicode characters in a
89438  *  packed format.  These tables are used to match non-ASCII
89439  *  characters of complex productions by resorting to a linear
89440  *  range-by-range comparison.  This is very slow, but is expected
89441  *  to be very rare in practical ECMAScript source code, and thus
89442  *  compactness is most important.
89443  *
89444  *  The tables are matched using uni_range_match() and the format
89445  *  is described in tools/extract_chars.py.
89446  */
89447 
89448 #if defined(DUK_USE_SOURCE_NONBMP)
89449 /* IdentifierStart production with ASCII excluded */
89450 /* duk_unicode_ids_noa[] */
89451 /*
89452  *  Automatically generated by extract_chars.py, do not edit!
89453  */
89454 
89455 const duk_uint8_t duk_unicode_ids_noa[1063] = {
89456 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
89457 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
89458 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
89459 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
89460 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,
89461 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,
89462 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,
89463 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
89464 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,
89465 98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,
89466 2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,
89467 35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,
89468 227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,
89469 21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,
89470 175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,
89471 79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,
89472 32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,
89473 32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,
89474 87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,
89475 254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242,
89476 127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243,
89477 95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,
89478 243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,
89479 143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,
89480 48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,
89481 223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,
89482 18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,
89483 127,10,207,73,69,53,53,50,241,91,47,10,47,3,33,46,61,241,79,107,243,127,37,
89484 255,223,13,79,33,242,31,16,239,14,111,22,191,14,63,20,87,36,241,207,142,
89485 240,79,20,95,20,95,24,159,36,248,239,254,2,154,240,107,127,138,83,2,241,
89486 194,20,3,240,123,240,122,240,255,51,240,50,27,240,107,240,175,56,242,135,
89487 31,50,15,1,50,34,240,191,30,240,212,240,223,21,114,240,207,13,242,107,240,
89488 107,240,62,240,47,96,243,159,41,242,62,242,63,254,32,79,37,243,223,29,241,
89489 47,9,240,207,20,241,191,19,64,223,32,240,3,240,112,32,241,95,2,47,9,244,
89490 102,32,35,46,41,143,31,241,135,49,63,6,38,33,36,64,240,64,212,249,15,37,
89491 240,67,242,127,32,240,97,32,250,175,31,241,179,241,111,32,240,96,242,223,
89492 27,244,127,10,255,224,122,243,15,17,15,242,11,241,136,15,7,12,241,131,63,
89493 40,242,159,249,130,241,95,3,15,35,240,239,98,98,18,241,111,7,15,254,26,223,
89494 254,40,207,88,245,255,3,251,79,254,155,15,254,50,31,254,236,95,254,19,159,
89495 255,0,16,173,255,225,43,143,15,246,63,14,240,79,32,240,35,241,31,5,111,3,
89496 255,226,100,243,92,15,52,207,50,31,16,255,240,0,109,255,5,255,225,229,255,
89497 240,1,64,31,254,1,31,67,255,224,126,255,231,248,245,182,196,136,159,255,0,
89498 6,90,244,82,243,114,19,3,19,50,178,2,98,243,18,51,114,98,240,194,50,66,4,
89499 98,255,224,70,63,9,47,9,47,15,47,9,47,15,47,9,47,15,47,9,47,15,47,9,39,255,
89500 239,40,251,95,45,243,79,254,59,3,47,11,33,32,48,41,35,32,32,112,80,32,32,
89501 34,33,32,48,32,32,32,32,33,32,51,38,35,35,32,41,47,1,98,36,47,1,255,240,0,
89502 3,143,255,0,149,201,241,191,254,242,124,252,227,255,240,0,87,79,0,255,240,
89503 0,194,63,254,177,63,254,17,0,
89504 };
89505 #else
89506 /* IdentifierStart production with ASCII and non-BMP excluded */
89507 /* duk_unicode_ids_noabmp[] */
89508 /*
89509  *  Automatically generated by extract_chars.py, do not edit!
89510  */
89511 
89512 const duk_uint8_t duk_unicode_ids_noabmp[626] = {
89513 249,176,176,80,111,7,47,15,47,254,11,197,191,0,72,2,15,115,66,19,50,7,2,34,
89514 2,240,66,244,50,247,185,249,98,241,99,8,241,127,58,240,182,47,31,241,191,
89515 21,18,245,50,15,1,24,27,35,15,2,2,240,239,15,244,156,15,10,241,26,21,6,240,
89516 101,10,4,15,9,240,152,175,39,240,82,127,56,242,100,15,4,8,159,1,240,5,115,
89517 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,
89518 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,
89519 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,
89520 12,38,31,16,5,114,34,240,114,146,68,15,18,2,31,1,31,4,114,34,241,147,15,2,
89521 6,41,47,10,86,240,36,240,130,130,3,111,44,242,2,29,111,44,18,3,18,3,7,50,
89522 98,34,2,3,18,50,26,3,66,15,7,63,18,15,49,114,241,79,13,79,101,241,191,6,15,
89523 2,85,52,4,24,37,205,15,3,241,98,6,3,241,178,255,224,63,35,54,32,35,63,25,
89524 35,63,17,35,54,32,35,62,47,41,35,63,51,241,127,0,240,47,70,53,79,254,21,
89525 227,240,18,240,166,243,180,168,194,63,0,240,47,0,240,47,0,194,47,1,242,79,
89526 21,5,15,53,244,137,67,241,34,6,243,107,240,255,35,240,227,76,241,197,240,
89527 175,40,240,122,242,95,68,15,79,241,255,3,111,41,240,238,27,241,207,12,241,
89528 79,27,43,241,67,143,82,50,52,26,251,15,50,255,224,8,53,63,22,53,55,32,32,
89529 32,47,15,63,37,38,32,66,38,67,53,92,98,38,246,96,224,240,44,245,112,80,57,
89530 32,68,112,32,32,35,42,51,100,80,240,63,25,255,233,107,241,242,241,242,247,
89531 87,52,29,241,98,6,3,242,136,15,2,240,122,98,98,98,98,98,98,98,111,66,15,
89532 254,12,146,240,184,132,52,95,70,114,47,74,35,111,26,63,78,240,63,11,242,
89533 127,0,255,224,244,255,240,0,138,143,60,255,240,4,13,223,7,255,227,127,243,
89534 95,30,63,253,79,0,177,240,111,31,240,47,15,63,64,241,152,63,87,63,20,39,
89535 243,26,34,35,47,7,240,255,36,240,15,34,243,5,64,32,223,12,191,7,240,191,13,
89536 143,31,240,224,240,36,41,180,47,25,240,146,39,240,111,7,64,79,34,32,65,52,
89537 48,32,240,162,58,130,213,53,53,166,38,47,27,41,191,99,240,255,255,0,26,150,
89538 223,7,95,33,255,240,0,255,143,254,6,3,245,175,24,109,70,2,146,194,66,2,18,
89539 18,245,207,19,255,224,93,240,79,48,63,38,241,171,246,100,47,119,241,111,10,
89540 127,10,207,73,69,53,53,50,0,
89541 };
89542 #endif
89543 
89544 #if defined(DUK_USE_SOURCE_NONBMP)
89545 /* IdentifierStart production with Letter and ASCII excluded */
89546 /* duk_unicode_ids_m_let_noa[] */
89547 /*
89548  *  Automatically generated by extract_chars.py, do not edit!
89549  */
89550 
89551 const duk_uint8_t duk_unicode_ids_m_let_noa[42] = {
89552 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
89553 249,255,240,4,148,79,37,255,224,192,9,15,120,79,255,0,15,30,245,240,
89554 };
89555 #else
89556 /* IdentifierStart production with Letter, ASCII, and non-BMP excluded */
89557 /* duk_unicode_ids_m_let_noabmp[] */
89558 /*
89559  *  Automatically generated by extract_chars.py, do not edit!
89560  */
89561 
89562 const duk_uint8_t duk_unicode_ids_m_let_noabmp[24] = {
89563 255,240,0,94,18,255,233,99,241,51,63,254,215,32,240,184,240,2,255,240,6,89,
89564 249,0,
89565 };
89566 #endif
89567 
89568 #if defined(DUK_USE_SOURCE_NONBMP)
89569 /* IdentifierPart production with IdentifierStart and ASCII excluded */
89570 /* duk_unicode_idp_m_ids_noa[] */
89571 /*
89572  *  Automatically generated by extract_chars.py, do not edit!
89573  */
89574 
89575 const duk_uint8_t duk_unicode_idp_m_ids_noa[549] = {
89576 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
89577 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
89578 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
89579 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
89580 97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
89581 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35,
89582 242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,
89583 41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
89584 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
89585 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
89586 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
89587 57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0,
89588 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
89589 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
89590 242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,
89591 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
89592 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,15,254,27,16,253,64,
89593 248,116,255,224,25,159,254,68,178,33,99,241,162,80,249,113,255,228,13,47,
89594 39,239,17,159,1,63,31,175,39,151,47,22,210,159,37,13,47,34,218,36,159,68,
89595 183,15,146,182,151,63,42,2,99,19,42,11,19,100,79,178,240,42,159,72,240,77,
89596 159,199,99,143,13,31,68,240,31,1,159,67,201,159,69,229,159,254,9,169,255,
89597 224,11,159,26,98,57,10,175,32,240,15,254,8,151,39,240,41,242,175,6,45,246,
89598 197,64,33,38,32,153,255,240,3,191,169,247,132,242,214,240,185,255,226,235,
89599 241,239,2,63,255,0,59,254,31,255,0,3,186,68,89,115,111,16,63,134,47,254,71,
89600 223,34,255,224,244,242,117,242,41,15,0,15,8,66,239,254,68,70,47,1,54,33,36,
89601 255,231,153,111,95,102,159,255,12,6,154,254,0,
89602 };
89603 #else
89604 /* IdentifierPart production with IdentifierStart, ASCII, and non-BMP excluded */
89605 /* duk_unicode_idp_m_ids_noabmp[] */
89606 /*
89607  *  Automatically generated by extract_chars.py, do not edit!
89608  */
89609 
89610 const duk_uint8_t duk_unicode_idp_m_ids_noabmp[358] = {
89611 255,225,243,246,15,254,0,116,255,191,29,32,33,33,32,243,170,242,47,15,112,
89612 245,118,53,49,35,57,240,144,241,15,11,244,218,240,25,241,56,241,67,40,34,
89613 36,241,210,246,173,47,17,242,130,47,2,38,177,57,240,50,242,160,38,49,50,
89614 160,177,57,240,50,242,160,36,81,50,64,240,107,64,194,242,160,39,34,34,240,
89615 97,57,181,34,242,160,38,49,50,145,177,57,240,64,242,212,66,35,160,240,9,
89616 240,35,242,198,34,35,129,193,57,240,50,242,160,38,34,35,129,193,57,240,35,
89617 242,145,38,34,35,160,177,57,240,65,243,128,85,32,39,121,49,242,240,54,215,
89618 41,244,144,53,33,197,57,243,1,121,192,32,32,81,242,63,4,33,106,47,20,160,
89619 245,111,4,41,211,82,34,54,67,235,46,255,225,179,47,254,42,98,240,242,240,
89620 241,241,1,243,47,16,160,57,241,50,57,245,209,241,64,246,139,91,185,247,41,
89621 242,244,242,185,47,13,58,121,240,141,243,68,242,31,1,201,240,56,210,241,12,
89622 57,241,237,242,47,4,153,121,246,130,47,5,80,82,50,251,143,42,36,255,225,0,
89623 31,35,31,5,15,109,197,4,191,254,175,34,247,240,245,47,16,255,225,30,95,91,
89624 31,255,0,100,121,159,55,5,159,18,31,66,31,254,0,64,64,80,240,148,244,161,
89625 242,79,2,185,127,2,240,9,240,231,240,188,241,227,242,29,240,25,192,185,242,
89626 29,208,145,57,241,50,242,64,34,49,97,32,241,180,97,253,231,33,57,255,240,3,
89627 225,128,255,225,213,240,15,2,240,4,31,10,47,178,159,23,0,
89628 };
89629 #endif
89630 
89631 /*
89632  *  Case conversion tables generated using tools/extract_caseconv.py.
89633  */
89634 
89635 /* duk_unicode_caseconv_uc[] */
89636 /* duk_unicode_caseconv_lc[] */
89637 
89638 /*
89639  *  Automatically generated by extract_caseconv.py, do not edit!
89640  */
89641 
89642 const duk_uint8_t duk_unicode_caseconv_uc[1386] = {
89643 144,3,128,3,0,184,7,192,6,192,112,35,242,199,224,64,74,192,49,32,128,162,
89644 128,108,65,1,189,129,254,131,3,173,3,136,6,7,98,7,34,68,15,12,14,140,72,30,
89645 104,28,112,32,67,0,65,4,0,138,0,128,4,1,88,65,76,83,9,252,9,248,6,28,131,4,
89646 33,4,62,0,62,16,32,124,64,124,96,48,249,0,249,64,129,243,1,243,129,3,232,3,
89647 233,1,135,216,7,218,4,15,184,15,221,2,31,114,31,200,8,62,236,63,180,8,125,
89648 224,127,224,16,251,208,255,80,33,247,193,255,160,67,246,3,247,0,135,244,7,
89649 246,1,15,240,15,244,2,33,112,33,96,32,73,160,73,108,104,176,192,176,1,121,
89650 104,0,133,2,106,183,1,58,10,31,232,63,228,38,162,1,1,1,0,48,2,102,2,100,12,
89651 4,232,4,228,64,10,88,10,81,112,23,160,23,144,96,48,96,48,64,128,104,64,104,
89652 1,128,218,0,217,130,1,206,1,205,16,3,190,3,188,36,7,228,7,224,160,17,24,17,
89653 16,144,36,112,36,96,160,110,32,110,0,128,246,64,246,6,2,48,130,48,17,4,139,
89654 4,138,54,9,132,9,130,28,19,68,19,65,128,240,8,240,4,177,234,17,234,6,3,234,
89655 35,235,33,11,26,11,25,193,150,64,150,64,50,44,236,44,235,5,76,131,76,128,
89656 94,154,6,154,0,117,57,29,57,16,122,115,58,115,35,244,239,84,239,32,169,223,
89657 233,223,130,211,200,211,200,2,167,151,167,150,21,79,107,79,104,8,112,26,
89658 208,26,192,64,56,160,56,128,192,113,128,113,1,128,249,0,248,130,2,128,1,
89659 166,4,7,240,7,238,8,177,204,177,200,16,96,49,0,48,224,128,110,64,110,1,1,
89660 51,83,213,2,0,48,35,192,35,176,64,77,32,50,192,139,73,196,49,193,127,48,2,
89661 212,14,112,3,252,5,224,4,196,1,36,5,252,1,76,6,0,9,12,6,72,6,68,6,84,7,216,
89662 6,100,6,96,6,104,8,244,6,120,8,128,6,160,6,156,6,252,7,220,7,116,6,56,7,
89663 204,7,196,9,64,177,188,9,68,177,180,9,72,177,192,9,76,6,4,9,80,6,24,9,100,
89664 6,60,9,108,6,64,9,114,158,172,9,128,6,76,9,134,158,176,9,140,6,80,9,150,
89665 158,52,9,160,6,92,9,172,177,136,9,178,158,180,9,196,177,184,9,200,6,116,9,
89666 212,6,124,9,244,177,144,10,30,158,196,10,32,6,184,10,36,9,16,10,48,9,20,10,
89667 72,6,220,10,118,158,200,10,122,158,192,13,20,14,100,13,220,13,216,14,176,
89668 14,24,15,8,14,140,15,48,14,48,15,64,14,72,15,68,14,96,15,84,14,152,15,88,
89669 14,128,15,92,15,60,15,192,14,104,15,196,14,132,15,200,15,228,15,204,13,252,
89670 15,212,14,84,19,60,19,0,114,0,16,72,114,4,16,80,114,8,16,120,114,20,16,136,
89671 114,24,16,168,114,28,17,136,114,34,153,40,117,230,157,244,117,244,177,140,
89672 122,108,121,128,126,248,14,100,127,148,127,176,133,56,132,200,134,16,134,
89673 12,177,132,177,128,177,148,8,232,177,152,8,248,179,204,179,202,158,50,158,
89674 46,173,78,158,207,48,6,252,0,166,0,166,2,147,1,94,0,39,0,248,64,9,64,97,
89675 128,114,24,28,200,24,64,24,8,29,134,7,74,6,16,6,2,11,15,2,154,130,169,15,
89676 75,64,9,0,102,35,210,240,2,160,24,64,244,196,0,174,6,20,61,51,0,44,129,133,
89677 15,77,64,8,32,87,195,234,16,29,40,24,152,250,150,7,74,6,38,6,0,62,169,129,
89678 210,129,137,129,128,143,171,96,116,160,98,96,104,67,240,16,248,64,28,200,
89679 252,12,62,18,7,50,63,5,15,133,1,204,143,193,195,225,96,115,35,240,144,248,
89680 96,28,200,252,44,62,26,7,50,63,13,15,135,1,204,143,195,195,225,224,115,35,
89681 241,16,248,64,28,200,252,76,62,18,7,50,63,21,15,133,1,204,143,197,195,225,
89682 96,115,35,241,144,248,96,28,200,252,108,62,26,7,50,63,29,15,135,1,204,143,
89683 199,195,225,224,115,35,242,16,249,64,28,200,252,140,62,82,7,50,63,37,15,
89684 149,1,204,143,201,195,229,96,115,35,242,144,249,96,28,200,252,172,62,90,7,
89685 50,63,45,15,151,1,204,143,203,195,229,224,115,35,243,16,249,64,28,200,252,
89686 204,62,82,7,50,63,53,15,149,1,204,143,205,195,229,96,115,35,243,144,249,96,
89687 28,200,252,236,62,90,7,50,63,61,15,151,1,204,143,207,195,229,224,115,35,
89688 244,16,251,64,28,200,253,12,62,210,7,50,63,69,15,181,1,204,143,209,195,237,
89689 96,115,35,244,144,251,96,28,200,253,44,62,218,7,50,63,77,15,183,1,204,143,
89690 211,195,237,224,115,35,245,16,251,64,28,200,253,76,62,210,7,50,63,85,15,
89691 181,1,204,143,213,195,237,96,115,35,245,144,251,96,28,200,253,108,62,218,7,
89692 50,63,93,15,183,1,204,143,215,195,237,224,115,35,246,80,253,208,28,200,253,
89693 156,7,34,7,50,63,105,1,195,1,204,143,219,64,114,32,104,67,246,248,28,136,
89694 26,16,28,200,253,228,7,34,7,50,63,133,15,229,1,204,143,225,192,114,224,115,
89695 35,248,144,28,72,28,200,254,52,7,46,6,132,63,143,129,203,129,161,1,204,143,
89696 230,64,114,224,115,35,250,88,28,200,24,64,24,0,254,158,7,50,6,16,6,2,63,
89697 173,1,204,129,161,15,235,224,115,32,97,0,104,67,252,88,29,40,24,64,24,0,
89698 255,30,7,74,6,16,6,2,63,201,1,208,129,137,143,243,64,116,160,104,67,252,
89699 248,29,40,24,64,26,16,255,148,63,244,7,50,63,231,1,212,129,204,143,250,64,
89700 113,224,115,35,254,208,29,72,26,16,255,190,7,82,6,132,7,50,63,249,1,212,
89701 129,204,253,128,64,8,192,8,223,96,48,2,48,2,79,216,20,0,140,0,153,246,7,
89702 128,35,0,35,0,36,253,130,96,8,192,8,192,9,159,96,176,2,152,2,167,216,52,0,
89703 166,0,169,246,39,2,162,2,163,125,138,64,168,128,166,191,98,176,42,32,41,
89704 223,216,180,10,156,10,141,246,47,2,162,2,158,128,
89705 };
89706 const duk_uint8_t duk_unicode_caseconv_lc[680] = {
89707 152,3,0,3,128,184,6,192,7,192,112,24,144,37,96,64,54,32,81,64,128,226,0,
89708 235,65,129,199,1,230,130,3,145,3,177,34,7,70,7,134,36,15,244,13,236,24,32,
89709 0,34,129,0,65,0,67,4,0,166,32,172,41,132,40,11,64,19,9,208,85,184,80,19,
89710 240,19,248,12,62,16,62,0,32,124,96,124,64,48,249,64,249,0,129,243,129,243,
89711 1,3,233,3,232,1,135,218,7,216,4,15,196,15,192,8,31,152,31,144,16,63,80,63,
89712 64,32,126,224,126,192,16,253,208,251,128,33,252,129,247,32,131,251,3,250,0,
89713 135,246,135,221,129,15,244,15,240,2,31,234,31,122,4,63,240,62,240,8,127,
89714 232,125,240,17,11,1,11,129,2,75,98,77,3,69,128,5,134,11,203,31,128,143,193,
89715 127,144,255,160,154,140,4,0,4,4,192,9,144,9,152,48,19,144,19,161,0,41,64,
89716 41,101,192,94,64,94,129,128,193,0,193,130,1,160,1,161,6,3,102,3,104,8,7,44,
89717 7,48,72,14,240,14,248,144,31,32,31,48,64,63,0,63,37,0,136,128,136,196,129,
89718 35,1,35,133,3,112,3,113,4,7,176,7,178,48,17,128,17,132,136,36,80,36,89,176,
89719 76,16,76,32,224,154,0,154,44,7,128,7,128,101,143,80,15,80,176,31,89,31,81,
89720 8,88,206,88,208,12,178,0,178,5,145,103,89,103,96,42,100,10,100,18,244,208,
89721 20,208,35,169,200,169,200,195,211,153,83,153,159,167,121,167,122,5,78,253,
89722 78,254,22,158,66,158,68,21,60,181,60,184,170,123,74,123,80,67,0,211,1,64,2,
89723 1,172,1,173,4,3,136,3,140,12,7,20,7,24,16,31,184,31,192,34,199,34,199,48,
89724 65,128,195,128,196,2,1,184,1,185,5,79,84,4,204,8,0,192,101,128,154,65,1,29,
89725 129,30,2,16,199,45,39,5,251,240,23,128,15,240,24,16,37,48,24,96,37,64,24,
89726 224,29,208,24,240,37,144,25,0,37,176,25,16,25,32,25,48,38,0,25,64,38,48,25,
89727 112,38,128,25,128,25,144,25,208,39,32,25,240,39,80,26,112,26,128,26,224,40,
89728 128,27,112,41,32,31,16,31,48,31,96,25,80,31,112,27,240,34,0,25,224,35,162,
89729 198,80,35,208,25,160,35,226,198,96,36,48,24,0,36,64,40,144,36,80,40,192,55,
89730 96,55,112,55,240,63,48,56,96,58,192,56,192,60,192,60,240,61,112,63,64,59,
89731 128,63,144,63,32,76,0,76,241,233,224,13,241,251,193,251,49,252,193,252,49,
89732 254,193,254,81,255,193,255,50,18,96,60,146,18,160,6,178,18,176,14,82,19,34,
89733 20,226,24,50,24,66,198,2,198,18,198,32,38,178,198,49,215,210,198,64,39,210,
89734 198,208,37,18,198,224,39,18,198,240,37,2,199,0,37,34,207,34,207,58,119,209,
89735 215,154,120,186,120,202,120,208,38,90,122,176,37,202,122,192,38,26,122,208,
89736 38,202,123,0,41,234,123,16,40,122,123,32,41,218,123,58,181,48,32,38,16,3,
89737 72,24,56,
89738 };
89739 
89740 #if defined(DUK_USE_REGEXP_CANON_WORKAROUND)
89741 /*
89742  *  Automatically generated by extract_caseconv.py, do not edit!
89743  */
89744 
89745 const duk_uint16_t duk_unicode_re_canon_lookup[65536] = {
89746 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,
89747 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,
89748 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,
89749 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,
89750 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,123,124,125,
89751 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
89752 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
89753 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
89754 180,924,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
89755 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
89756 216,217,218,219,220,221,222,223,192,193,194,195,196,197,198,199,200,201,
89757 202,203,204,205,206,207,208,209,210,211,212,213,214,247,216,217,218,219,
89758 220,221,222,376,256,256,258,258,260,260,262,262,264,264,266,266,268,268,
89759 270,270,272,272,274,274,276,276,278,278,280,280,282,282,284,284,286,286,
89760 288,288,290,290,292,292,294,294,296,296,298,298,300,300,302,302,304,305,
89761 306,306,308,308,310,310,312,313,313,315,315,317,317,319,319,321,321,323,
89762 323,325,325,327,327,329,330,330,332,332,334,334,336,336,338,338,340,340,
89763 342,342,344,344,346,346,348,348,350,350,352,352,354,354,356,356,358,358,
89764 360,360,362,362,364,364,366,366,368,368,370,370,372,372,374,374,376,377,
89765 377,379,379,381,381,383,579,385,386,386,388,388,390,391,391,393,394,395,
89766 395,397,398,399,400,401,401,403,404,502,406,407,408,408,573,411,412,413,
89767 544,415,416,416,418,418,420,420,422,423,423,425,426,427,428,428,430,431,
89768 431,433,434,435,435,437,437,439,440,440,442,443,444,444,446,503,448,449,
89769 450,451,452,452,452,455,455,455,458,458,458,461,461,463,463,465,465,467,
89770 467,469,469,471,471,473,473,475,475,398,478,478,480,480,482,482,484,484,
89771 486,486,488,488,490,490,492,492,494,494,496,497,497,497,500,500,502,503,
89772 504,504,506,506,508,508,510,510,512,512,514,514,516,516,518,518,520,520,
89773 522,522,524,524,526,526,528,528,530,530,532,532,534,534,536,536,538,538,
89774 540,540,542,542,544,545,546,546,548,548,550,550,552,552,554,554,556,556,
89775 558,558,560,560,562,562,564,565,566,567,568,569,570,571,571,573,574,11390,
89776 11391,577,577,579,580,581,582,582,584,584,586,586,588,588,590,590,11375,
89777 11373,11376,385,390,597,393,394,600,399,602,400,42923L,605,606,607,403,
89778 42924L,610,404,612,42893L,42922L,615,407,406,42926L,11362,42925L,621,622,
89779 412,624,11374,413,627,628,415,630,631,632,633,634,635,636,11364,638,639,
89780 422,641,642,425,644,645,646,42929L,430,580,433,434,581,653,654,655,656,657,
89781 439,659,660,661,662,663,664,665,666,667,668,42930L,42928L,671,672,673,674,
89782 675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,
89783 693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,
89784 711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,
89785 729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,
89786 747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,
89787 765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,
89788 783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,
89789 801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,
89790 819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,
89791 921,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,
89792 855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,
89793 873,874,875,876,877,878,879,880,880,882,882,884,885,886,886,888,889,890,
89794 1021,1022,1023,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,
89795 909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,
89796 927,928,929,930,931,932,933,934,935,936,937,938,939,902,904,905,906,944,
89797 913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,
89798 931,932,933,934,935,936,937,938,939,908,910,911,975,914,920,978,979,980,
89799 934,928,975,984,984,986,986,988,988,990,990,992,992,994,994,996,996,998,
89800 998,1000,1000,1002,1002,1004,1004,1006,1006,922,929,1017,895,1012,917,1014,
89801 1015,1015,1017,1018,1018,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,
89802 1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,
89803 1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,
89804 1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1040,1041,1042,
89805 1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,
89806 1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,
89807 1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,
89808 1120,1120,1122,1122,1124,1124,1126,1126,1128,1128,1130,1130,1132,1132,1134,
89809 1134,1136,1136,1138,1138,1140,1140,1142,1142,1144,1144,1146,1146,1148,1148,
89810 1150,1150,1152,1152,1154,1155,1156,1157,1158,1159,1160,1161,1162,1162,1164,
89811 1164,1166,1166,1168,1168,1170,1170,1172,1172,1174,1174,1176,1176,1178,1178,
89812 1180,1180,1182,1182,1184,1184,1186,1186,1188,1188,1190,1190,1192,1192,1194,
89813 1194,1196,1196,1198,1198,1200,1200,1202,1202,1204,1204,1206,1206,1208,1208,
89814 1210,1210,1212,1212,1214,1214,1216,1217,1217,1219,1219,1221,1221,1223,1223,
89815 1225,1225,1227,1227,1229,1229,1216,1232,1232,1234,1234,1236,1236,1238,1238,
89816 1240,1240,1242,1242,1244,1244,1246,1246,1248,1248,1250,1250,1252,1252,1254,
89817 1254,1256,1256,1258,1258,1260,1260,1262,1262,1264,1264,1266,1266,1268,1268,
89818 1270,1270,1272,1272,1274,1274,1276,1276,1278,1278,1280,1280,1282,1282,1284,
89819 1284,1286,1286,1288,1288,1290,1290,1292,1292,1294,1294,1296,1296,1298,1298,
89820 1300,1300,1302,1302,1304,1304,1306,1306,1308,1308,1310,1310,1312,1312,1314,
89821 1314,1316,1316,1318,1318,1320,1320,1322,1322,1324,1324,1326,1326,1328,1329,
89822 1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,
89823 1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,
89824 1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,
89825 1375,1376,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,
89826 1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,
89827 1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1415,1416,1417,1418,1419,
89828 1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,
89829 1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,
89830 1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,
89831 1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,
89832 1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,
89833 1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,
89834 1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,
89835 1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,
89836 1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,
89837 1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,
89838 1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,
89839 1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,
89840 1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,
89841 1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,
89842 1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,
89843 1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,
89844 1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,
89845 1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,
89846 1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,
89847 1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,
89848 1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,
89849 1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,
89850 1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,
89851 1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,
89852 1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,
89853 1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,
89854 1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,
89855 1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,
89856 1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,
89857 1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,
89858 1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,
89859 1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,
89860 1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,
89861 1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,
89862 1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,
89863 1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,
89864 1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,
89865 1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,
89866 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,
89867 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,
89868 2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,
89869 2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,
89870 2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,
89871 2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,
89872 2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,
89873 2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,
89874 2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,
89875 2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,
89876 2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,
89877 2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,
89878 2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,
89879 2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,
89880 2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,
89881 2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,
89882 2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,
89883 2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,
89884 2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,
89885 2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,
89886 2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,
89887 2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,
89888 2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,
89889 2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,
89890 2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,
89891 2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,
89892 2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,
89893 2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,
89894 2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,
89895 2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,
89896 2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,
89897 2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,
89898 2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,
89899 2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,
89900 2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,
89901 2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,
89902 2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,
89903 2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,
89904 2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,
89905 2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,
89906 2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,
89907 2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,
89908 2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,
89909 2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,
89910 2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,
89911 2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,
89912 2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,
89913 2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,
89914 2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,
89915 2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,
89916 2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,
89917 2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,
89918 2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,
89919 2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,
89920 2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,
89921 2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,
89922 2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,
89923 2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,
89924 2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,
89925 2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,
89926 2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,
89927 2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,
89928 2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,
89929 2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,
89930 2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,
89931 2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,
89932 2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,
89933 2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,
89934 3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,
89935 3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,
89936 3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,
89937 3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,
89938 3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,
89939 3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,
89940 3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,
89941 3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,
89942 3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,
89943 3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,
89944 3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,
89945 3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,
89946 3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,
89947 3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,
89948 3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,
89949 3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,
89950 3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,
89951 3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,
89952 3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,
89953 3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,
89954 3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,
89955 3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,
89956 3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,
89957 3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,
89958 3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,
89959 3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,
89960 3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,
89961 3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,
89962 3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,
89963 3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,
89964 3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,
89965 3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,
89966 3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,
89967 3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,
89968 3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,
89969 3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,
89970 3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,
89971 3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,
89972 3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,
89973 3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,
89974 3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,
89975 3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,
89976 3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,
89977 3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,
89978 3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,
89979 3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,
89980 3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,
89981 3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,
89982 3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,
89983 3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,
89984 3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,
89985 3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,
89986 3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,
89987 3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,
89988 3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,
89989 3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,
89990 3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,
89991 3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,
89992 3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,
89993 3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,
89994 3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,
89995 3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,
89996 3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,
89997 3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,
89998 3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,
89999 3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,
90000 4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,
90001 4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,
90002 4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,
90003 4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,
90004 4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,
90005 4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,
90006 4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,
90007 4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,
90008 4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,
90009 4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,
90010 4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,
90011 4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,
90012 4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,
90013 4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,
90014 4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,
90015 4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,
90016 4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,
90017 4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,
90018 4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,
90019 4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,
90020 4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,
90021 4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,
90022 4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,
90023 4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,
90024 4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,
90025 4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,
90026 4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,
90027 4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,
90028 4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,
90029 4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,
90030 4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,
90031 4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,
90032 4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,
90033 4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,
90034 4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,
90035 4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,
90036 4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,
90037 4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,
90038 4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,
90039 4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,
90040 4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,
90041 4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,
90042 4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,
90043 4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,
90044 4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,
90045 4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,
90046 4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,
90047 4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,
90048 4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,
90049 4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,
90050 4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,
90051 4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,
90052 4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,
90053 4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,
90054 4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,
90055 4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,
90056 4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,
90057 4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,
90058 4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,
90059 4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,
90060 4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,
90061 4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,
90062 4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,
90063 4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,
90064 4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,
90065 4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,
90066 4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,
90067 5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,
90068 5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,
90069 5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,
90070 5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,
90071 5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,
90072 5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,
90073 5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,
90074 5110,5111,5104,5105,5106,5107,5108,5109,5118,5119,5120,5121,5122,5123,5124,
90075 5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,
90076 5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,
90077 5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,
90078 5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,
90079 5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,
90080 5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,
90081 5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,
90082 5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,
90083 5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,
90084 5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,
90085 5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,
90086 5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,
90087 5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,
90088 5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,
90089 5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,
90090 5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,
90091 5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,
90092 5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,
90093 5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,
90094 5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,
90095 5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,
90096 5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,
90097 5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,
90098 5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,
90099 5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,
90100 5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,
90101 5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,
90102 5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,
90103 5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,
90104 5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,
90105 5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,
90106 5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,
90107 5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,
90108 5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,
90109 5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,
90110 5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,
90111 5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,
90112 5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,
90113 5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,
90114 5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,
90115 5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,
90116 5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,
90117 5755,5756,5757,5758,5759,5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,
90118 5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,
90119 5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,
90120 5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,
90121 5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,
90122 5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,
90123 5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,
90124 5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,
90125 5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,
90126 5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,
90127 5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,
90128 5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,
90129 5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,
90130 5950,5951,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,
90131 5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,
90132 5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,
90133 5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,
90134 6010,6011,6012,6013,6014,6015,6016,6017,6018,6019,6020,6021,6022,6023,6024,
90135 6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,
90136 6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,
90137 6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,
90138 6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,
90139 6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,
90140 6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,
90141 6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,
90142 6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140,6141,6142,6143,6144,
90143 6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,
90144 6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,
90145 6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,
90146 6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,
90147 6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,
90148 6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,
90149 6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,
90150 6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,
90151 6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,
90152 6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,
90153 6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,
90154 6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,
90155 6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,
90156 6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,
90157 6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,
90158 6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,
90159 6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,6399,
90160 6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,
90161 6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,
90162 6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,
90163 6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,
90164 6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,
90165 6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,
90166 6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,
90167 6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,
90168 6520,6521,6522,6523,6524,6525,6526,6527,6528,6529,6530,6531,6532,6533,6534,
90169 6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,
90170 6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,
90171 6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,
90172 6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6593,6594,
90173 6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,
90174 6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,
90175 6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,
90176 6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,
90177 6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,
90178 6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,
90179 6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,
90180 6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,
90181 6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,
90182 6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,
90183 6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,
90184 6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,
90185 6775,6776,6777,6778,6779,6780,6781,6782,6783,6784,6785,6786,6787,6788,6789,
90186 6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,
90187 6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,
90188 6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,
90189 6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,
90190 6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,
90191 6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,
90192 6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,
90193 6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908,6909,
90194 6910,6911,6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,
90195 6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,
90196 6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,
90197 6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,
90198 6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6981,6982,6983,6984,
90199 6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,
90200 7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,
90201 7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,
90202 7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,
90203 7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,
90204 7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,
90205 7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,
90206 7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100,7101,7102,7103,7104,
90207 7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,
90208 7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,
90209 7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,
90210 7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,
90211 7165,7166,7167,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,
90212 7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,
90213 7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,
90214 7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,
90215 7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,
90216 7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,
90217 7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,
90218 7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,
90219 7285,7286,7287,7288,7289,7290,7291,7292,7293,7294,7295,1042,1044,1054,1057,
90220 1058,1058,1066,1122,42570L,7305,7306,7307,7308,7309,7310,7311,7312,7313,
90221 7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,
90222 7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,
90223 7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,
90224 7359,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,
90225 7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,
90226 7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,
90227 7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,
90228 7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,
90229 7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,
90230 7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,
90231 7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,
90232 7479,7480,7481,7482,7483,7484,7485,7486,7487,7488,7489,7490,7491,7492,7493,
90233 7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,
90234 7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,
90235 7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,
90236 7539,7540,7541,7542,7543,7544,42877L,7546,7547,7548,11363,7550,7551,7552,
90237 7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,
90238 7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,
90239 7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,
90240 7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,
90241 7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,
90242 7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,
90243 7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,
90244 7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,
90245 7673,7674,7675,7676,7677,7678,7679,7680,7680,7682,7682,7684,7684,7686,7686,
90246 7688,7688,7690,7690,7692,7692,7694,7694,7696,7696,7698,7698,7700,7700,7702,
90247 7702,7704,7704,7706,7706,7708,7708,7710,7710,7712,7712,7714,7714,7716,7716,
90248 7718,7718,7720,7720,7722,7722,7724,7724,7726,7726,7728,7728,7730,7730,7732,
90249 7732,7734,7734,7736,7736,7738,7738,7740,7740,7742,7742,7744,7744,7746,7746,
90250 7748,7748,7750,7750,7752,7752,7754,7754,7756,7756,7758,7758,7760,7760,7762,
90251 7762,7764,7764,7766,7766,7768,7768,7770,7770,7772,7772,7774,7774,7776,7776,
90252 7778,7778,7780,7780,7782,7782,7784,7784,7786,7786,7788,7788,7790,7790,7792,
90253 7792,7794,7794,7796,7796,7798,7798,7800,7800,7802,7802,7804,7804,7806,7806,
90254 7808,7808,7810,7810,7812,7812,7814,7814,7816,7816,7818,7818,7820,7820,7822,
90255 7822,7824,7824,7826,7826,7828,7828,7830,7831,7832,7833,7834,7776,7836,7837,
90256 7838,7839,7840,7840,7842,7842,7844,7844,7846,7846,7848,7848,7850,7850,7852,
90257 7852,7854,7854,7856,7856,7858,7858,7860,7860,7862,7862,7864,7864,7866,7866,
90258 7868,7868,7870,7870,7872,7872,7874,7874,7876,7876,7878,7878,7880,7880,7882,
90259 7882,7884,7884,7886,7886,7888,7888,7890,7890,7892,7892,7894,7894,7896,7896,
90260 7898,7898,7900,7900,7902,7902,7904,7904,7906,7906,7908,7908,7910,7910,7912,
90261 7912,7914,7914,7916,7916,7918,7918,7920,7920,7922,7922,7924,7924,7926,7926,
90262 7928,7928,7930,7930,7932,7932,7934,7934,7944,7945,7946,7947,7948,7949,7950,
90263 7951,7944,7945,7946,7947,7948,7949,7950,7951,7960,7961,7962,7963,7964,7965,
90264 7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7976,7977,7978,7979,7980,
90265 7981,7982,7983,7976,7977,7978,7979,7980,7981,7982,7983,7992,7993,7994,7995,
90266 7996,7997,7998,7999,7992,7993,7994,7995,7996,7997,7998,7999,8008,8009,8010,
90267 8011,8012,8013,8006,8007,8008,8009,8010,8011,8012,8013,8014,8015,8016,8025,
90268 8018,8027,8020,8029,8022,8031,8024,8025,8026,8027,8028,8029,8030,8031,8040,
90269 8041,8042,8043,8044,8045,8046,8047,8040,8041,8042,8043,8044,8045,8046,8047,
90270 8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,8062,
90271 8063,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,
90272 8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,
90273 8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,
90274 8108,8109,8110,8111,8120,8121,8114,8115,8116,8117,8118,8119,8120,8121,8122,
90275 8123,8124,8125,921,8127,8128,8129,8130,8131,8132,8133,8134,8135,8136,8137,
90276 8138,8139,8140,8141,8142,8143,8152,8153,8146,8147,8148,8149,8150,8151,8152,
90277 8153,8154,8155,8156,8157,8158,8159,8168,8169,8162,8163,8164,8172,8166,8167,
90278 8168,8169,8170,8171,8172,8173,8174,8175,8176,8177,8178,8179,8180,8181,8182,
90279 8183,8184,8185,8186,8187,8188,8189,8190,8191,8192,8193,8194,8195,8196,8197,
90280 8198,8199,8200,8201,8202,8203,8204,8205,8206,8207,8208,8209,8210,8211,8212,
90281 8213,8214,8215,8216,8217,8218,8219,8220,8221,8222,8223,8224,8225,8226,8227,
90282 8228,8229,8230,8231,8232,8233,8234,8235,8236,8237,8238,8239,8240,8241,8242,
90283 8243,8244,8245,8246,8247,8248,8249,8250,8251,8252,8253,8254,8255,8256,8257,
90284 8258,8259,8260,8261,8262,8263,8264,8265,8266,8267,8268,8269,8270,8271,8272,
90285 8273,8274,8275,8276,8277,8278,8279,8280,8281,8282,8283,8284,8285,8286,8287,
90286 8288,8289,8290,8291,8292,8293,8294,8295,8296,8297,8298,8299,8300,8301,8302,
90287 8303,8304,8305,8306,8307,8308,8309,8310,8311,8312,8313,8314,8315,8316,8317,
90288 8318,8319,8320,8321,8322,8323,8324,8325,8326,8327,8328,8329,8330,8331,8332,
90289 8333,8334,8335,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,
90290 8348,8349,8350,8351,8352,8353,8354,8355,8356,8357,8358,8359,8360,8361,8362,
90291 8363,8364,8365,8366,8367,8368,8369,8370,8371,8372,8373,8374,8375,8376,8377,
90292 8378,8379,8380,8381,8382,8383,8384,8385,8386,8387,8388,8389,8390,8391,8392,
90293 8393,8394,8395,8396,8397,8398,8399,8400,8401,8402,8403,8404,8405,8406,8407,
90294 8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,
90295 8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,8433,8434,8435,8436,8437,
90296 8438,8439,8440,8441,8442,8443,8444,8445,8446,8447,8448,8449,8450,8451,8452,
90297 8453,8454,8455,8456,8457,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,
90298 8468,8469,8470,8471,8472,8473,8474,8475,8476,8477,8478,8479,8480,8481,8482,
90299 8483,8484,8485,8486,8487,8488,8489,8490,8491,8492,8493,8494,8495,8496,8497,
90300 8498,8499,8500,8501,8502,8503,8504,8505,8506,8507,8508,8509,8510,8511,8512,
90301 8513,8514,8515,8516,8517,8518,8519,8520,8521,8522,8523,8524,8525,8498,8527,
90302 8528,8529,8530,8531,8532,8533,8534,8535,8536,8537,8538,8539,8540,8541,8542,
90303 8543,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,
90304 8558,8559,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,
90305 8557,8558,8559,8576,8577,8578,8579,8579,8581,8582,8583,8584,8585,8586,8587,
90306 8588,8589,8590,8591,8592,8593,8594,8595,8596,8597,8598,8599,8600,8601,8602,
90307 8603,8604,8605,8606,8607,8608,8609,8610,8611,8612,8613,8614,8615,8616,8617,
90308 8618,8619,8620,8621,8622,8623,8624,8625,8626,8627,8628,8629,8630,8631,8632,
90309 8633,8634,8635,8636,8637,8638,8639,8640,8641,8642,8643,8644,8645,8646,8647,
90310 8648,8649,8650,8651,8652,8653,8654,8655,8656,8657,8658,8659,8660,8661,8662,
90311 8663,8664,8665,8666,8667,8668,8669,8670,8671,8672,8673,8674,8675,8676,8677,
90312 8678,8679,8680,8681,8682,8683,8684,8685,8686,8687,8688,8689,8690,8691,8692,
90313 8693,8694,8695,8696,8697,8698,8699,8700,8701,8702,8703,8704,8705,8706,8707,
90314 8708,8709,8710,8711,8712,8713,8714,8715,8716,8717,8718,8719,8720,8721,8722,
90315 8723,8724,8725,8726,8727,8728,8729,8730,8731,8732,8733,8734,8735,8736,8737,
90316 8738,8739,8740,8741,8742,8743,8744,8745,8746,8747,8748,8749,8750,8751,8752,
90317 8753,8754,8755,8756,8757,8758,8759,8760,8761,8762,8763,8764,8765,8766,8767,
90318 8768,8769,8770,8771,8772,8773,8774,8775,8776,8777,8778,8779,8780,8781,8782,
90319 8783,8784,8785,8786,8787,8788,8789,8790,8791,8792,8793,8794,8795,8796,8797,
90320 8798,8799,8800,8801,8802,8803,8804,8805,8806,8807,8808,8809,8810,8811,8812,
90321 8813,8814,8815,8816,8817,8818,8819,8820,8821,8822,8823,8824,8825,8826,8827,
90322 8828,8829,8830,8831,8832,8833,8834,8835,8836,8837,8838,8839,8840,8841,8842,
90323 8843,8844,8845,8846,8847,8848,8849,8850,8851,8852,8853,8854,8855,8856,8857,
90324 8858,8859,8860,8861,8862,8863,8864,8865,8866,8867,8868,8869,8870,8871,8872,
90325 8873,8874,8875,8876,8877,8878,8879,8880,8881,8882,8883,8884,8885,8886,8887,
90326 8888,8889,8890,8891,8892,8893,8894,8895,8896,8897,8898,8899,8900,8901,8902,
90327 8903,8904,8905,8906,8907,8908,8909,8910,8911,8912,8913,8914,8915,8916,8917,
90328 8918,8919,8920,8921,8922,8923,8924,8925,8926,8927,8928,8929,8930,8931,8932,
90329 8933,8934,8935,8936,8937,8938,8939,8940,8941,8942,8943,8944,8945,8946,8947,
90330 8948,8949,8950,8951,8952,8953,8954,8955,8956,8957,8958,8959,8960,8961,8962,
90331 8963,8964,8965,8966,8967,8968,8969,8970,8971,8972,8973,8974,8975,8976,8977,
90332 8978,8979,8980,8981,8982,8983,8984,8985,8986,8987,8988,8989,8990,8991,8992,
90333 8993,8994,8995,8996,8997,8998,8999,9000,9001,9002,9003,9004,9005,9006,9007,
90334 9008,9009,9010,9011,9012,9013,9014,9015,9016,9017,9018,9019,9020,9021,9022,
90335 9023,9024,9025,9026,9027,9028,9029,9030,9031,9032,9033,9034,9035,9036,9037,
90336 9038,9039,9040,9041,9042,9043,9044,9045,9046,9047,9048,9049,9050,9051,9052,
90337 9053,9054,9055,9056,9057,9058,9059,9060,9061,9062,9063,9064,9065,9066,9067,
90338 9068,9069,9070,9071,9072,9073,9074,9075,9076,9077,9078,9079,9080,9081,9082,
90339 9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,
90340 9098,9099,9100,9101,9102,9103,9104,9105,9106,9107,9108,9109,9110,9111,9112,
90341 9113,9114,9115,9116,9117,9118,9119,9120,9121,9122,9123,9124,9125,9126,9127,
90342 9128,9129,9130,9131,9132,9133,9134,9135,9136,9137,9138,9139,9140,9141,9142,
90343 9143,9144,9145,9146,9147,9148,9149,9150,9151,9152,9153,9154,9155,9156,9157,
90344 9158,9159,9160,9161,9162,9163,9164,9165,9166,9167,9168,9169,9170,9171,9172,
90345 9173,9174,9175,9176,9177,9178,9179,9180,9181,9182,9183,9184,9185,9186,9187,
90346 9188,9189,9190,9191,9192,9193,9194,9195,9196,9197,9198,9199,9200,9201,9202,
90347 9203,9204,9205,9206,9207,9208,9209,9210,9211,9212,9213,9214,9215,9216,9217,
90348 9218,9219,9220,9221,9222,9223,9224,9225,9226,9227,9228,9229,9230,9231,9232,
90349 9233,9234,9235,9236,9237,9238,9239,9240,9241,9242,9243,9244,9245,9246,9247,
90350 9248,9249,9250,9251,9252,9253,9254,9255,9256,9257,9258,9259,9260,9261,9262,
90351 9263,9264,9265,9266,9267,9268,9269,9270,9271,9272,9273,9274,9275,9276,9277,
90352 9278,9279,9280,9281,9282,9283,9284,9285,9286,9287,9288,9289,9290,9291,9292,
90353 9293,9294,9295,9296,9297,9298,9299,9300,9301,9302,9303,9304,9305,9306,9307,
90354 9308,9309,9310,9311,9312,9313,9314,9315,9316,9317,9318,9319,9320,9321,9322,
90355 9323,9324,9325,9326,9327,9328,9329,9330,9331,9332,9333,9334,9335,9336,9337,
90356 9338,9339,9340,9341,9342,9343,9344,9345,9346,9347,9348,9349,9350,9351,9352,
90357 9353,9354,9355,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,
90358 9368,9369,9370,9371,9372,9373,9374,9375,9376,9377,9378,9379,9380,9381,9382,
90359 9383,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,
90360 9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,
90361 9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,9398,9399,9400,9401,
90362 9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,
90363 9417,9418,9419,9420,9421,9422,9423,9450,9451,9452,9453,9454,9455,9456,9457,
90364 9458,9459,9460,9461,9462,9463,9464,9465,9466,9467,9468,9469,9470,9471,9472,
90365 9473,9474,9475,9476,9477,9478,9479,9480,9481,9482,9483,9484,9485,9486,9487,
90366 9488,9489,9490,9491,9492,9493,9494,9495,9496,9497,9498,9499,9500,9501,9502,
90367 9503,9504,9505,9506,9507,9508,9509,9510,9511,9512,9513,9514,9515,9516,9517,
90368 9518,9519,9520,9521,9522,9523,9524,9525,9526,9527,9528,9529,9530,9531,9532,
90369 9533,9534,9535,9536,9537,9538,9539,9540,9541,9542,9543,9544,9545,9546,9547,
90370 9548,9549,9550,9551,9552,9553,9554,9555,9556,9557,9558,9559,9560,9561,9562,
90371 9563,9564,9565,9566,9567,9568,9569,9570,9571,9572,9573,9574,9575,9576,9577,
90372 9578,9579,9580,9581,9582,9583,9584,9585,9586,9587,9588,9589,9590,9591,9592,
90373 9593,9594,9595,9596,9597,9598,9599,9600,9601,9602,9603,9604,9605,9606,9607,
90374 9608,9609,9610,9611,9612,9613,9614,9615,9616,9617,9618,9619,9620,9621,9622,
90375 9623,9624,9625,9626,9627,9628,9629,9630,9631,9632,9633,9634,9635,9636,9637,
90376 9638,9639,9640,9641,9642,9643,9644,9645,9646,9647,9648,9649,9650,9651,9652,
90377 9653,9654,9655,9656,9657,9658,9659,9660,9661,9662,9663,9664,9665,9666,9667,
90378 9668,9669,9670,9671,9672,9673,9674,9675,9676,9677,9678,9679,9680,9681,9682,
90379 9683,9684,9685,9686,9687,9688,9689,9690,9691,9692,9693,9694,9695,9696,9697,
90380 9698,9699,9700,9701,9702,9703,9704,9705,9706,9707,9708,9709,9710,9711,9712,
90381 9713,9714,9715,9716,9717,9718,9719,9720,9721,9722,9723,9724,9725,9726,9727,
90382 9728,9729,9730,9731,9732,9733,9734,9735,9736,9737,9738,9739,9740,9741,9742,
90383 9743,9744,9745,9746,9747,9748,9749,9750,9751,9752,9753,9754,9755,9756,9757,
90384 9758,9759,9760,9761,9762,9763,9764,9765,9766,9767,9768,9769,9770,9771,9772,
90385 9773,9774,9775,9776,9777,9778,9779,9780,9781,9782,9783,9784,9785,9786,9787,
90386 9788,9789,9790,9791,9792,9793,9794,9795,9796,9797,9798,9799,9800,9801,9802,
90387 9803,9804,9805,9806,9807,9808,9809,9810,9811,9812,9813,9814,9815,9816,9817,
90388 9818,9819,9820,9821,9822,9823,9824,9825,9826,9827,9828,9829,9830,9831,9832,
90389 9833,9834,9835,9836,9837,9838,9839,9840,9841,9842,9843,9844,9845,9846,9847,
90390 9848,9849,9850,9851,9852,9853,9854,9855,9856,9857,9858,9859,9860,9861,9862,
90391 9863,9864,9865,9866,9867,9868,9869,9870,9871,9872,9873,9874,9875,9876,9877,
90392 9878,9879,9880,9881,9882,9883,9884,9885,9886,9887,9888,9889,9890,9891,9892,
90393 9893,9894,9895,9896,9897,9898,9899,9900,9901,9902,9903,9904,9905,9906,9907,
90394 9908,9909,9910,9911,9912,9913,9914,9915,9916,9917,9918,9919,9920,9921,9922,
90395 9923,9924,9925,9926,9927,9928,9929,9930,9931,9932,9933,9934,9935,9936,9937,
90396 9938,9939,9940,9941,9942,9943,9944,9945,9946,9947,9948,9949,9950,9951,9952,
90397 9953,9954,9955,9956,9957,9958,9959,9960,9961,9962,9963,9964,9965,9966,9967,
90398 9968,9969,9970,9971,9972,9973,9974,9975,9976,9977,9978,9979,9980,9981,9982,
90399 9983,9984,9985,9986,9987,9988,9989,9990,9991,9992,9993,9994,9995,9996,9997,
90400 9998,9999,10000,10001,10002,10003,10004,10005,10006,10007,10008,10009,
90401 10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10020,10021,
90402 10022,10023,10024,10025,10026,10027,10028,10029,10030,10031,10032,10033,
90403 10034,10035,10036,10037,10038,10039,10040,10041,10042,10043,10044,10045,
90404 10046,10047,10048,10049,10050,10051,10052,10053,10054,10055,10056,10057,
90405 10058,10059,10060,10061,10062,10063,10064,10065,10066,10067,10068,10069,
90406 10070,10071,10072,10073,10074,10075,10076,10077,10078,10079,10080,10081,
90407 10082,10083,10084,10085,10086,10087,10088,10089,10090,10091,10092,10093,
90408 10094,10095,10096,10097,10098,10099,10100,10101,10102,10103,10104,10105,
90409 10106,10107,10108,10109,10110,10111,10112,10113,10114,10115,10116,10117,
90410 10118,10119,10120,10121,10122,10123,10124,10125,10126,10127,10128,10129,
90411 10130,10131,10132,10133,10134,10135,10136,10137,10138,10139,10140,10141,
90412 10142,10143,10144,10145,10146,10147,10148,10149,10150,10151,10152,10153,
90413 10154,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,
90414 10166,10167,10168,10169,10170,10171,10172,10173,10174,10175,10176,10177,
90415 10178,10179,10180,10181,10182,10183,10184,10185,10186,10187,10188,10189,
90416 10190,10191,10192,10193,10194,10195,10196,10197,10198,10199,10200,10201,
90417 10202,10203,10204,10205,10206,10207,10208,10209,10210,10211,10212,10213,
90418 10214,10215,10216,10217,10218,10219,10220,10221,10222,10223,10224,10225,
90419 10226,10227,10228,10229,10230,10231,10232,10233,10234,10235,10236,10237,
90420 10238,10239,10240,10241,10242,10243,10244,10245,10246,10247,10248,10249,
90421 10250,10251,10252,10253,10254,10255,10256,10257,10258,10259,10260,10261,
90422 10262,10263,10264,10265,10266,10267,10268,10269,10270,10271,10272,10273,
90423 10274,10275,10276,10277,10278,10279,10280,10281,10282,10283,10284,10285,
90424 10286,10287,10288,10289,10290,10291,10292,10293,10294,10295,10296,10297,
90425 10298,10299,10300,10301,10302,10303,10304,10305,10306,10307,10308,10309,
90426 10310,10311,10312,10313,10314,10315,10316,10317,10318,10319,10320,10321,
90427 10322,10323,10324,10325,10326,10327,10328,10329,10330,10331,10332,10333,
90428 10334,10335,10336,10337,10338,10339,10340,10341,10342,10343,10344,10345,
90429 10346,10347,10348,10349,10350,10351,10352,10353,10354,10355,10356,10357,
90430 10358,10359,10360,10361,10362,10363,10364,10365,10366,10367,10368,10369,
90431 10370,10371,10372,10373,10374,10375,10376,10377,10378,10379,10380,10381,
90432 10382,10383,10384,10385,10386,10387,10388,10389,10390,10391,10392,10393,
90433 10394,10395,10396,10397,10398,10399,10400,10401,10402,10403,10404,10405,
90434 10406,10407,10408,10409,10410,10411,10412,10413,10414,10415,10416,10417,
90435 10418,10419,10420,10421,10422,10423,10424,10425,10426,10427,10428,10429,
90436 10430,10431,10432,10433,10434,10435,10436,10437,10438,10439,10440,10441,
90437 10442,10443,10444,10445,10446,10447,10448,10449,10450,10451,10452,10453,
90438 10454,10455,10456,10457,10458,10459,10460,10461,10462,10463,10464,10465,
90439 10466,10467,10468,10469,10470,10471,10472,10473,10474,10475,10476,10477,
90440 10478,10479,10480,10481,10482,10483,10484,10485,10486,10487,10488,10489,
90441 10490,10491,10492,10493,10494,10495,10496,10497,10498,10499,10500,10501,
90442 10502,10503,10504,10505,10506,10507,10508,10509,10510,10511,10512,10513,
90443 10514,10515,10516,10517,10518,10519,10520,10521,10522,10523,10524,10525,
90444 10526,10527,10528,10529,10530,10531,10532,10533,10534,10535,10536,10537,
90445 10538,10539,10540,10541,10542,10543,10544,10545,10546,10547,10548,10549,
90446 10550,10551,10552,10553,10554,10555,10556,10557,10558,10559,10560,10561,
90447 10562,10563,10564,10565,10566,10567,10568,10569,10570,10571,10572,10573,
90448 10574,10575,10576,10577,10578,10579,10580,10581,10582,10583,10584,10585,
90449 10586,10587,10588,10589,10590,10591,10592,10593,10594,10595,10596,10597,
90450 10598,10599,10600,10601,10602,10603,10604,10605,10606,10607,10608,10609,
90451 10610,10611,10612,10613,10614,10615,10616,10617,10618,10619,10620,10621,
90452 10622,10623,10624,10625,10626,10627,10628,10629,10630,10631,10632,10633,
90453 10634,10635,10636,10637,10638,10639,10640,10641,10642,10643,10644,10645,
90454 10646,10647,10648,10649,10650,10651,10652,10653,10654,10655,10656,10657,
90455 10658,10659,10660,10661,10662,10663,10664,10665,10666,10667,10668,10669,
90456 10670,10671,10672,10673,10674,10675,10676,10677,10678,10679,10680,10681,
90457 10682,10683,10684,10685,10686,10687,10688,10689,10690,10691,10692,10693,
90458 10694,10695,10696,10697,10698,10699,10700,10701,10702,10703,10704,10705,
90459 10706,10707,10708,10709,10710,10711,10712,10713,10714,10715,10716,10717,
90460 10718,10719,10720,10721,10722,10723,10724,10725,10726,10727,10728,10729,
90461 10730,10731,10732,10733,10734,10735,10736,10737,10738,10739,10740,10741,
90462 10742,10743,10744,10745,10746,10747,10748,10749,10750,10751,10752,10753,
90463 10754,10755,10756,10757,10758,10759,10760,10761,10762,10763,10764,10765,
90464 10766,10767,10768,10769,10770,10771,10772,10773,10774,10775,10776,10777,
90465 10778,10779,10780,10781,10782,10783,10784,10785,10786,10787,10788,10789,
90466 10790,10791,10792,10793,10794,10795,10796,10797,10798,10799,10800,10801,
90467 10802,10803,10804,10805,10806,10807,10808,10809,10810,10811,10812,10813,
90468 10814,10815,10816,10817,10818,10819,10820,10821,10822,10823,10824,10825,
90469 10826,10827,10828,10829,10830,10831,10832,10833,10834,10835,10836,10837,
90470 10838,10839,10840,10841,10842,10843,10844,10845,10846,10847,10848,10849,
90471 10850,10851,10852,10853,10854,10855,10856,10857,10858,10859,10860,10861,
90472 10862,10863,10864,10865,10866,10867,10868,10869,10870,10871,10872,10873,
90473 10874,10875,10876,10877,10878,10879,10880,10881,10882,10883,10884,10885,
90474 10886,10887,10888,10889,10890,10891,10892,10893,10894,10895,10896,10897,
90475 10898,10899,10900,10901,10902,10903,10904,10905,10906,10907,10908,10909,
90476 10910,10911,10912,10913,10914,10915,10916,10917,10918,10919,10920,10921,
90477 10922,10923,10924,10925,10926,10927,10928,10929,10930,10931,10932,10933,
90478 10934,10935,10936,10937,10938,10939,10940,10941,10942,10943,10944,10945,
90479 10946,10947,10948,10949,10950,10951,10952,10953,10954,10955,10956,10957,
90480 10958,10959,10960,10961,10962,10963,10964,10965,10966,10967,10968,10969,
90481 10970,10971,10972,10973,10974,10975,10976,10977,10978,10979,10980,10981,
90482 10982,10983,10984,10985,10986,10987,10988,10989,10990,10991,10992,10993,
90483 10994,10995,10996,10997,10998,10999,11000,11001,11002,11003,11004,11005,
90484 11006,11007,11008,11009,11010,11011,11012,11013,11014,11015,11016,11017,
90485 11018,11019,11020,11021,11022,11023,11024,11025,11026,11027,11028,11029,
90486 11030,11031,11032,11033,11034,11035,11036,11037,11038,11039,11040,11041,
90487 11042,11043,11044,11045,11046,11047,11048,11049,11050,11051,11052,11053,
90488 11054,11055,11056,11057,11058,11059,11060,11061,11062,11063,11064,11065,
90489 11066,11067,11068,11069,11070,11071,11072,11073,11074,11075,11076,11077,
90490 11078,11079,11080,11081,11082,11083,11084,11085,11086,11087,11088,11089,
90491 11090,11091,11092,11093,11094,11095,11096,11097,11098,11099,11100,11101,
90492 11102,11103,11104,11105,11106,11107,11108,11109,11110,11111,11112,11113,
90493 11114,11115,11116,11117,11118,11119,11120,11121,11122,11123,11124,11125,
90494 11126,11127,11128,11129,11130,11131,11132,11133,11134,11135,11136,11137,
90495 11138,11139,11140,11141,11142,11143,11144,11145,11146,11147,11148,11149,
90496 11150,11151,11152,11153,11154,11155,11156,11157,11158,11159,11160,11161,
90497 11162,11163,11164,11165,11166,11167,11168,11169,11170,11171,11172,11173,
90498 11174,11175,11176,11177,11178,11179,11180,11181,11182,11183,11184,11185,
90499 11186,11187,11188,11189,11190,11191,11192,11193,11194,11195,11196,11197,
90500 11198,11199,11200,11201,11202,11203,11204,11205,11206,11207,11208,11209,
90501 11210,11211,11212,11213,11214,11215,11216,11217,11218,11219,11220,11221,
90502 11222,11223,11224,11225,11226,11227,11228,11229,11230,11231,11232,11233,
90503 11234,11235,11236,11237,11238,11239,11240,11241,11242,11243,11244,11245,
90504 11246,11247,11248,11249,11250,11251,11252,11253,11254,11255,11256,11257,
90505 11258,11259,11260,11261,11262,11263,11264,11265,11266,11267,11268,11269,
90506 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
90507 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
90508 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
90509 11306,11307,11308,11309,11310,11311,11264,11265,11266,11267,11268,11269,
90510 11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,
90511 11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,
90512 11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,
90513 11306,11307,11308,11309,11310,11359,11360,11360,11362,11363,11364,570,574,
90514 11367,11367,11369,11369,11371,11371,11373,11374,11375,11376,11377,11378,
90515 11378,11380,11381,11381,11383,11384,11385,11386,11387,11388,11389,11390,
90516 11391,11392,11392,11394,11394,11396,11396,11398,11398,11400,11400,11402,
90517 11402,11404,11404,11406,11406,11408,11408,11410,11410,11412,11412,11414,
90518 11414,11416,11416,11418,11418,11420,11420,11422,11422,11424,11424,11426,
90519 11426,11428,11428,11430,11430,11432,11432,11434,11434,11436,11436,11438,
90520 11438,11440,11440,11442,11442,11444,11444,11446,11446,11448,11448,11450,
90521 11450,11452,11452,11454,11454,11456,11456,11458,11458,11460,11460,11462,
90522 11462,11464,11464,11466,11466,11468,11468,11470,11470,11472,11472,11474,
90523 11474,11476,11476,11478,11478,11480,11480,11482,11482,11484,11484,11486,
90524 11486,11488,11488,11490,11490,11492,11493,11494,11495,11496,11497,11498,
90525 11499,11499,11501,11501,11503,11504,11505,11506,11506,11508,11509,11510,
90526 11511,11512,11513,11514,11515,11516,11517,11518,11519,4256,4257,4258,4259,
90527 4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,
90528 4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,
90529 4290,4291,4292,4293,11558,4295,11560,11561,11562,11563,11564,4301,11566,
90530 11567,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,
90531 11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,
90532 11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,
90533 11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,
90534 11615,11616,11617,11618,11619,11620,11621,11622,11623,11624,11625,11626,
90535 11627,11628,11629,11630,11631,11632,11633,11634,11635,11636,11637,11638,
90536 11639,11640,11641,11642,11643,11644,11645,11646,11647,11648,11649,11650,
90537 11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,
90538 11663,11664,11665,11666,11667,11668,11669,11670,11671,11672,11673,11674,
90539 11675,11676,11677,11678,11679,11680,11681,11682,11683,11684,11685,11686,
90540 11687,11688,11689,11690,11691,11692,11693,11694,11695,11696,11697,11698,
90541 11699,11700,11701,11702,11703,11704,11705,11706,11707,11708,11709,11710,
90542 11711,11712,11713,11714,11715,11716,11717,11718,11719,11720,11721,11722,
90543 11723,11724,11725,11726,11727,11728,11729,11730,11731,11732,11733,11734,
90544 11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,
90545 11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,
90546 11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,
90547 11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,
90548 11783,11784,11785,11786,11787,11788,11789,11790,11791,11792,11793,11794,
90549 11795,11796,11797,11798,11799,11800,11801,11802,11803,11804,11805,11806,
90550 11807,11808,11809,11810,11811,11812,11813,11814,11815,11816,11817,11818,
90551 11819,11820,11821,11822,11823,11824,11825,11826,11827,11828,11829,11830,
90552 11831,11832,11833,11834,11835,11836,11837,11838,11839,11840,11841,11842,
90553 11843,11844,11845,11846,11847,11848,11849,11850,11851,11852,11853,11854,
90554 11855,11856,11857,11858,11859,11860,11861,11862,11863,11864,11865,11866,
90555 11867,11868,11869,11870,11871,11872,11873,11874,11875,11876,11877,11878,
90556 11879,11880,11881,11882,11883,11884,11885,11886,11887,11888,11889,11890,
90557 11891,11892,11893,11894,11895,11896,11897,11898,11899,11900,11901,11902,
90558 11903,11904,11905,11906,11907,11908,11909,11910,11911,11912,11913,11914,
90559 11915,11916,11917,11918,11919,11920,11921,11922,11923,11924,11925,11926,
90560 11927,11928,11929,11930,11931,11932,11933,11934,11935,11936,11937,11938,
90561 11939,11940,11941,11942,11943,11944,11945,11946,11947,11948,11949,11950,
90562 11951,11952,11953,11954,11955,11956,11957,11958,11959,11960,11961,11962,
90563 11963,11964,11965,11966,11967,11968,11969,11970,11971,11972,11973,11974,
90564 11975,11976,11977,11978,11979,11980,11981,11982,11983,11984,11985,11986,
90565 11987,11988,11989,11990,11991,11992,11993,11994,11995,11996,11997,11998,
90566 11999,12000,12001,12002,12003,12004,12005,12006,12007,12008,12009,12010,
90567 12011,12012,12013,12014,12015,12016,12017,12018,12019,12020,12021,12022,
90568 12023,12024,12025,12026,12027,12028,12029,12030,12031,12032,12033,12034,
90569 12035,12036,12037,12038,12039,12040,12041,12042,12043,12044,12045,12046,
90570 12047,12048,12049,12050,12051,12052,12053,12054,12055,12056,12057,12058,
90571 12059,12060,12061,12062,12063,12064,12065,12066,12067,12068,12069,12070,
90572 12071,12072,12073,12074,12075,12076,12077,12078,12079,12080,12081,12082,
90573 12083,12084,12085,12086,12087,12088,12089,12090,12091,12092,12093,12094,
90574 12095,12096,12097,12098,12099,12100,12101,12102,12103,12104,12105,12106,
90575 12107,12108,12109,12110,12111,12112,12113,12114,12115,12116,12117,12118,
90576 12119,12120,12121,12122,12123,12124,12125,12126,12127,12128,12129,12130,
90577 12131,12132,12133,12134,12135,12136,12137,12138,12139,12140,12141,12142,
90578 12143,12144,12145,12146,12147,12148,12149,12150,12151,12152,12153,12154,
90579 12155,12156,12157,12158,12159,12160,12161,12162,12163,12164,12165,12166,
90580 12167,12168,12169,12170,12171,12172,12173,12174,12175,12176,12177,12178,
90581 12179,12180,12181,12182,12183,12184,12185,12186,12187,12188,12189,12190,
90582 12191,12192,12193,12194,12195,12196,12197,12198,12199,12200,12201,12202,
90583 12203,12204,12205,12206,12207,12208,12209,12210,12211,12212,12213,12214,
90584 12215,12216,12217,12218,12219,12220,12221,12222,12223,12224,12225,12226,
90585 12227,12228,12229,12230,12231,12232,12233,12234,12235,12236,12237,12238,
90586 12239,12240,12241,12242,12243,12244,12245,12246,12247,12248,12249,12250,
90587 12251,12252,12253,12254,12255,12256,12257,12258,12259,12260,12261,12262,
90588 12263,12264,12265,12266,12267,12268,12269,12270,12271,12272,12273,12274,
90589 12275,12276,12277,12278,12279,12280,12281,12282,12283,12284,12285,12286,
90590 12287,12288,12289,12290,12291,12292,12293,12294,12295,12296,12297,12298,
90591 12299,12300,12301,12302,12303,12304,12305,12306,12307,12308,12309,12310,
90592 12311,12312,12313,12314,12315,12316,12317,12318,12319,12320,12321,12322,
90593 12323,12324,12325,12326,12327,12328,12329,12330,12331,12332,12333,12334,
90594 12335,12336,12337,12338,12339,12340,12341,12342,12343,12344,12345,12346,
90595 12347,12348,12349,12350,12351,12352,12353,12354,12355,12356,12357,12358,
90596 12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,
90597 12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,
90598 12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,
90599 12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,
90600 12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,
90601 12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,
90602 12431,12432,12433,12434,12435,12436,12437,12438,12439,12440,12441,12442,
90603 12443,12444,12445,12446,12447,12448,12449,12450,12451,12452,12453,12454,
90604 12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,
90605 12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,
90606 12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,
90607 12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,
90608 12503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,
90609 12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,
90610 12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,
90611 12539,12540,12541,12542,12543,12544,12545,12546,12547,12548,12549,12550,
90612 12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,
90613 12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,
90614 12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,
90615 12587,12588,12589,12590,12591,12592,12593,12594,12595,12596,12597,12598,
90616 12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,
90617 12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,
90618 12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,
90619 12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,
90620 12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,
90621 12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,
90622 12671,12672,12673,12674,12675,12676,12677,12678,12679,12680,12681,12682,
90623 12683,12684,12685,12686,12687,12688,12689,12690,12691,12692,12693,12694,
90624 12695,12696,12697,12698,12699,12700,12701,12702,12703,12704,12705,12706,
90625 12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,
90626 12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,
90627 12731,12732,12733,12734,12735,12736,12737,12738,12739,12740,12741,12742,
90628 12743,12744,12745,12746,12747,12748,12749,12750,12751,12752,12753,12754,
90629 12755,12756,12757,12758,12759,12760,12761,12762,12763,12764,12765,12766,
90630 12767,12768,12769,12770,12771,12772,12773,12774,12775,12776,12777,12778,
90631 12779,12780,12781,12782,12783,12784,12785,12786,12787,12788,12789,12790,
90632 12791,12792,12793,12794,12795,12796,12797,12798,12799,12800,12801,12802,
90633 12803,12804,12805,12806,12807,12808,12809,12810,12811,12812,12813,12814,
90634 12815,12816,12817,12818,12819,12820,12821,12822,12823,12824,12825,12826,
90635 12827,12828,12829,12830,12831,12832,12833,12834,12835,12836,12837,12838,
90636 12839,12840,12841,12842,12843,12844,12845,12846,12847,12848,12849,12850,
90637 12851,12852,12853,12854,12855,12856,12857,12858,12859,12860,12861,12862,
90638 12863,12864,12865,12866,12867,12868,12869,12870,12871,12872,12873,12874,
90639 12875,12876,12877,12878,12879,12880,12881,12882,12883,12884,12885,12886,
90640 12887,12888,12889,12890,12891,12892,12893,12894,12895,12896,12897,12898,
90641 12899,12900,12901,12902,12903,12904,12905,12906,12907,12908,12909,12910,
90642 12911,12912,12913,12914,12915,12916,12917,12918,12919,12920,12921,12922,
90643 12923,12924,12925,12926,12927,12928,12929,12930,12931,12932,12933,12934,
90644 12935,12936,12937,12938,12939,12940,12941,12942,12943,12944,12945,12946,
90645 12947,12948,12949,12950,12951,12952,12953,12954,12955,12956,12957,12958,
90646 12959,12960,12961,12962,12963,12964,12965,12966,12967,12968,12969,12970,
90647 12971,12972,12973,12974,12975,12976,12977,12978,12979,12980,12981,12982,
90648 12983,12984,12985,12986,12987,12988,12989,12990,12991,12992,12993,12994,
90649 12995,12996,12997,12998,12999,13000,13001,13002,13003,13004,13005,13006,
90650 13007,13008,13009,13010,13011,13012,13013,13014,13015,13016,13017,13018,
90651 13019,13020,13021,13022,13023,13024,13025,13026,13027,13028,13029,13030,
90652 13031,13032,13033,13034,13035,13036,13037,13038,13039,13040,13041,13042,
90653 13043,13044,13045,13046,13047,13048,13049,13050,13051,13052,13053,13054,
90654 13055,13056,13057,13058,13059,13060,13061,13062,13063,13064,13065,13066,
90655 13067,13068,13069,13070,13071,13072,13073,13074,13075,13076,13077,13078,
90656 13079,13080,13081,13082,13083,13084,13085,13086,13087,13088,13089,13090,
90657 13091,13092,13093,13094,13095,13096,13097,13098,13099,13100,13101,13102,
90658 13103,13104,13105,13106,13107,13108,13109,13110,13111,13112,13113,13114,
90659 13115,13116,13117,13118,13119,13120,13121,13122,13123,13124,13125,13126,
90660 13127,13128,13129,13130,13131,13132,13133,13134,13135,13136,13137,13138,
90661 13139,13140,13141,13142,13143,13144,13145,13146,13147,13148,13149,13150,
90662 13151,13152,13153,13154,13155,13156,13157,13158,13159,13160,13161,13162,
90663 13163,13164,13165,13166,13167,13168,13169,13170,13171,13172,13173,13174,
90664 13175,13176,13177,13178,13179,13180,13181,13182,13183,13184,13185,13186,
90665 13187,13188,13189,13190,13191,13192,13193,13194,13195,13196,13197,13198,
90666 13199,13200,13201,13202,13203,13204,13205,13206,13207,13208,13209,13210,
90667 13211,13212,13213,13214,13215,13216,13217,13218,13219,13220,13221,13222,
90668 13223,13224,13225,13226,13227,13228,13229,13230,13231,13232,13233,13234,
90669 13235,13236,13237,13238,13239,13240,13241,13242,13243,13244,13245,13246,
90670 13247,13248,13249,13250,13251,13252,13253,13254,13255,13256,13257,13258,
90671 13259,13260,13261,13262,13263,13264,13265,13266,13267,13268,13269,13270,
90672 13271,13272,13273,13274,13275,13276,13277,13278,13279,13280,13281,13282,
90673 13283,13284,13285,13286,13287,13288,13289,13290,13291,13292,13293,13294,
90674 13295,13296,13297,13298,13299,13300,13301,13302,13303,13304,13305,13306,
90675 13307,13308,13309,13310,13311,13312,13313,13314,13315,13316,13317,13318,
90676 13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,
90677 13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,
90678 13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,
90679 13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,
90680 13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,
90681 13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,
90682 13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,
90683 13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,
90684 13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,13426,
90685 13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,
90686 13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,
90687 13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,
90688 13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,
90689 13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,
90690 13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,
90691 13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,
90692 13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,
90693 13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,
90694 13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,
90695 13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,
90696 13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,
90697 13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,
90698 13583,13584,13585,13586,13587,13588,13589,13590,13591,13592,13593,13594,
90699 13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,
90700 13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,
90701 13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,
90702 13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,
90703 13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,
90704 13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,
90705 13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,
90706 13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,
90707 13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,
90708 13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,
90709 13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,
90710 13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,
90711 13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,
90712 13751,13752,13753,13754,13755,13756,13757,13758,13759,13760,13761,13762,
90713 13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,
90714 13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,
90715 13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,
90716 13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,
90717 13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,
90718 13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,
90719 13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,
90720 13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,
90721 13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,
90722 13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,
90723 13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,
90724 13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,
90725 13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,
90726 13919,13920,13921,13922,13923,13924,13925,13926,13927,13928,13929,13930,
90727 13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,
90728 13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,
90729 13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,
90730 13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,
90731 13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,
90732 13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,
90733 14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,
90734 14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,
90735 14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,
90736 14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,
90737 14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,
90738 14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,
90739 14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,
90740 14087,14088,14089,14090,14091,14092,14093,14094,14095,14096,14097,14098,
90741 14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,
90742 14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,
90743 14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,
90744 14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,
90745 14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,
90746 14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,
90747 14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,
90748 14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,
90749 14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,
90750 14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,
90751 14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,
90752 14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,
90753 14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,
90754 14255,14256,14257,14258,14259,14260,14261,14262,14263,14264,14265,14266,
90755 14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,
90756 14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,
90757 14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,
90758 14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,
90759 14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,
90760 14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,
90761 14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,
90762 14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,
90763 14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,
90764 14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,
90765 14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,
90766 14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,
90767 14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,
90768 14423,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,
90769 14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,
90770 14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,
90771 14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,
90772 14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,
90773 14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,
90774 14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,
90775 14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,
90776 14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,
90777 14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,
90778 14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,
90779 14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,
90780 14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,
90781 14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,14589,14590,
90782 14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,
90783 14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,
90784 14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,
90785 14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,
90786 14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,
90787 14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,
90788 14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,
90789 14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,
90790 14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,
90791 14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,
90792 14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,
90793 14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,
90794 14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,
90795 14747,14748,14749,14750,14751,14752,14753,14754,14755,14756,14757,14758,
90796 14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,
90797 14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,
90798 14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,
90799 14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,
90800 14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,
90801 14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,
90802 14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,
90803 14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,
90804 14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,
90805 14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,
90806 14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,
90807 14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,
90808 14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,
90809 14915,14916,14917,14918,14919,14920,14921,14922,14923,14924,14925,14926,
90810 14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,
90811 14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,
90812 14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,
90813 14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,
90814 14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,
90815 14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,
90816 14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,
90817 15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,
90818 15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,
90819 15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,
90820 15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,
90821 15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,
90822 15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,
90823 15083,15084,15085,15086,15087,15088,15089,15090,15091,15092,15093,15094,
90824 15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,
90825 15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,
90826 15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,
90827 15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,
90828 15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,
90829 15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,
90830 15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,
90831 15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,
90832 15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,
90833 15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,
90834 15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,
90835 15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,
90836 15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,
90837 15251,15252,15253,15254,15255,15256,15257,15258,15259,15260,15261,15262,
90838 15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,
90839 15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,
90840 15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,
90841 15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,
90842 15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,
90843 15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,
90844 15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,
90845 15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,
90846 15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,
90847 15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,
90848 15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,
90849 15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,
90850 15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,
90851 15419,15420,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,
90852 15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,
90853 15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,
90854 15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,
90855 15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,
90856 15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,
90857 15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,
90858 15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,
90859 15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,
90860 15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,
90861 15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,
90862 15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,
90863 15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,
90864 15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,15586,
90865 15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,
90866 15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,
90867 15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,
90868 15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,
90869 15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,
90870 15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,
90871 15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,
90872 15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,
90873 15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,
90874 15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,
90875 15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,
90876 15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,
90877 15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,
90878 15743,15744,15745,15746,15747,15748,15749,15750,15751,15752,15753,15754,
90879 15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,
90880 15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,
90881 15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,
90882 15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,
90883 15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,
90884 15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,
90885 15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,
90886 15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,
90887 15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,
90888 15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,
90889 15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,
90890 15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,
90891 15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,
90892 15911,15912,15913,15914,15915,15916,15917,15918,15919,15920,15921,15922,
90893 15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,
90894 15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,
90895 15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,
90896 15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,
90897 15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,
90898 15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,
90899 15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,
90900 16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,
90901 16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,
90902 16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,
90903 16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,
90904 16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,
90905 16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,
90906 16079,16080,16081,16082,16083,16084,16085,16086,16087,16088,16089,16090,
90907 16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,
90908 16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,
90909 16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,
90910 16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,
90911 16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,
90912 16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,
90913 16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,
90914 16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,
90915 16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,
90916 16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,
90917 16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,
90918 16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,
90919 16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,
90920 16247,16248,16249,16250,16251,16252,16253,16254,16255,16256,16257,16258,
90921 16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,
90922 16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,
90923 16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,
90924 16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,
90925 16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,
90926 16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,
90927 16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,
90928 16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,
90929 16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,
90930 16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,
90931 16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,
90932 16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,
90933 16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,
90934 16415,16416,16417,16418,16419,16420,16421,16422,16423,16424,16425,16426,
90935 16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,
90936 16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,
90937 16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,
90938 16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,
90939 16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,
90940 16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,
90941 16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,
90942 16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,
90943 16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,
90944 16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,
90945 16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,
90946 16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,
90947 16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,
90948 16583,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,
90949 16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,
90950 16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,
90951 16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,
90952 16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,
90953 16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,
90954 16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,
90955 16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,
90956 16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,
90957 16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,
90958 16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,
90959 16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,
90960 16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,
90961 16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749,16750,
90962 16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,
90963 16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,
90964 16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,
90965 16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,
90966 16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,
90967 16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,
90968 16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,
90969 16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,
90970 16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,
90971 16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,
90972 16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,
90973 16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,
90974 16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,
90975 16907,16908,16909,16910,16911,16912,16913,16914,16915,16916,16917,16918,
90976 16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,
90977 16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,
90978 16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,
90979 16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,
90980 16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,
90981 16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,
90982 16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,
90983 17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,
90984 17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,
90985 17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,
90986 17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,
90987 17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,
90988 17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,
90989 17075,17076,17077,17078,17079,17080,17081,17082,17083,17084,17085,17086,
90990 17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,
90991 17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,
90992 17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,
90993 17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,
90994 17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,
90995 17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,
90996 17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,
90997 17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,
90998 17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,
90999 17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,
91000 17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,
91001 17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,
91002 17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,
91003 17243,17244,17245,17246,17247,17248,17249,17250,17251,17252,17253,17254,
91004 17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,
91005 17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,
91006 17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,
91007 17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,
91008 17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,
91009 17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,
91010 17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,
91011 17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,
91012 17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,
91013 17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,
91014 17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,
91015 17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,
91016 17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,
91017 17411,17412,17413,17414,17415,17416,17417,17418,17419,17420,17421,17422,
91018 17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,
91019 17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,
91020 17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,
91021 17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,
91022 17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,
91023 17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,
91024 17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,
91025 17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,
91026 17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,
91027 17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,
91028 17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,
91029 17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,
91030 17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,
91031 17579,17580,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,
91032 17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,
91033 17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,
91034 17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,
91035 17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,
91036 17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,
91037 17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,
91038 17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,
91039 17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,
91040 17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,
91041 17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,
91042 17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,
91043 17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,
91044 17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746,
91045 17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,
91046 17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,
91047 17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,
91048 17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,
91049 17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,
91050 17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,
91051 17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,
91052 17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,
91053 17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,
91054 17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,
91055 17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,
91056 17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,
91057 17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,
91058 17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,17913,17914,
91059 17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,
91060 17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,
91061 17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,
91062 17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,
91063 17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,
91064 17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,
91065 17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,
91066 17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,
91067 18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,
91068 18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,
91069 18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,
91070 18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,
91071 18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,
91072 18071,18072,18073,18074,18075,18076,18077,18078,18079,18080,18081,18082,
91073 18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,
91074 18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,
91075 18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,
91076 18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,
91077 18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,
91078 18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,
91079 18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,
91080 18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,
91081 18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,
91082 18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,
91083 18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,
91084 18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,
91085 18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,
91086 18239,18240,18241,18242,18243,18244,18245,18246,18247,18248,18249,18250,
91087 18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,
91088 18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,
91089 18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,
91090 18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,
91091 18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,
91092 18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,
91093 18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,
91094 18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,
91095 18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,
91096 18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,
91097 18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,
91098 18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,
91099 18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,
91100 18407,18408,18409,18410,18411,18412,18413,18414,18415,18416,18417,18418,
91101 18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,
91102 18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,
91103 18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,
91104 18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,
91105 18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,
91106 18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,
91107 18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,
91108 18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,
91109 18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,
91110 18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,
91111 18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,
91112 18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,
91113 18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,
91114 18575,18576,18577,18578,18579,18580,18581,18582,18583,18584,18585,18586,
91115 18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,
91116 18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,
91117 18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,
91118 18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,
91119 18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,
91120 18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,
91121 18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,
91122 18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,
91123 18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,
91124 18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,
91125 18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,
91126 18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,
91127 18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,
91128 18743,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,
91129 18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,
91130 18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,
91131 18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,
91132 18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,
91133 18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,
91134 18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,
91135 18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,
91136 18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,
91137 18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,
91138 18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,
91139 18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,
91140 18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,
91141 18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,18910,
91142 18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,
91143 18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,
91144 18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,
91145 18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,
91146 18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,
91147 18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,
91148 18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,
91149 18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,
91150 19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,
91151 19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,
91152 19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,
91153 19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,
91154 19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,
91155 19067,19068,19069,19070,19071,19072,19073,19074,19075,19076,19077,19078,
91156 19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,
91157 19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,
91158 19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,
91159 19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,
91160 19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,
91161 19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,
91162 19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,
91163 19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,
91164 19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,
91165 19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,
91166 19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,
91167 19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,
91168 19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,
91169 19235,19236,19237,19238,19239,19240,19241,19242,19243,19244,19245,19246,
91170 19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,
91171 19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,
91172 19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,
91173 19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,
91174 19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,
91175 19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,
91176 19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,
91177 19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,
91178 19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,
91179 19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,
91180 19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,
91181 19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,
91182 19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,
91183 19403,19404,19405,19406,19407,19408,19409,19410,19411,19412,19413,19414,
91184 19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,
91185 19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,
91186 19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,
91187 19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,
91188 19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,
91189 19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,
91190 19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,
91191 19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,
91192 19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,
91193 19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,
91194 19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,
91195 19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,
91196 19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,
91197 19571,19572,19573,19574,19575,19576,19577,19578,19579,19580,19581,19582,
91198 19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,
91199 19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,
91200 19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,
91201 19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,
91202 19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,
91203 19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,
91204 19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,
91205 19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,
91206 19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,
91207 19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,
91208 19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,
91209 19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,
91210 19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,
91211 19739,19740,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,
91212 19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,
91213 19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,
91214 19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,
91215 19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,
91216 19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,
91217 19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,
91218 19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,
91219 19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,
91220 19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,
91221 19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,
91222 19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,
91223 19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19894,
91224 19895,19896,19897,19898,19899,19900,19901,19902,19903,19904,19905,19906,
91225 19907,19908,19909,19910,19911,19912,19913,19914,19915,19916,19917,19918,
91226 19919,19920,19921,19922,19923,19924,19925,19926,19927,19928,19929,19930,
91227 19931,19932,19933,19934,19935,19936,19937,19938,19939,19940,19941,19942,
91228 19943,19944,19945,19946,19947,19948,19949,19950,19951,19952,19953,19954,
91229 19955,19956,19957,19958,19959,19960,19961,19962,19963,19964,19965,19966,
91230 19967,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,
91231 19979,19980,19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,
91232 19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,
91233 20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,
91234 20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,
91235 20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,
91236 20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,
91237 20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,
91238 20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,
91239 20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,
91240 20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,
91241 20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,
91242 20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,
91243 20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,
91244 20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,
91245 20147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,
91246 20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,
91247 20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,
91248 20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,
91249 20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,
91250 20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,
91251 20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,
91252 20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,
91253 20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,
91254 20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,
91255 20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,
91256 20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,
91257 20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,
91258 20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20313,20314,
91259 20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,
91260 20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,
91261 20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,
91262 20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,
91263 20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,
91264 20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,
91265 20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,
91266 20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,
91267 20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,
91268 20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,
91269 20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,
91270 20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,
91271 20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,
91272 20471,20472,20473,20474,20475,20476,20477,20478,20479,20480,20481,20482,
91273 20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,
91274 20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,
91275 20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,
91276 20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,
91277 20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,
91278 20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,
91279 20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,
91280 20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,
91281 20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,
91282 20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,
91283 20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,
91284 20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,
91285 20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,
91286 20639,20640,20641,20642,20643,20644,20645,20646,20647,20648,20649,20650,
91287 20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,
91288 20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,
91289 20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,
91290 20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,
91291 20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,
91292 20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,
91293 20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,
91294 20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,
91295 20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,
91296 20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,
91297 20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,
91298 20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,
91299 20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,
91300 20807,20808,20809,20810,20811,20812,20813,20814,20815,20816,20817,20818,
91301 20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,
91302 20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,
91303 20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,
91304 20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,
91305 20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,
91306 20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,
91307 20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,
91308 20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,
91309 20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,
91310 20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,
91311 20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,
91312 20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,
91313 20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,
91314 20975,20976,20977,20978,20979,20980,20981,20982,20983,20984,20985,20986,
91315 20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,
91316 20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,
91317 21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,
91318 21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,
91319 21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,
91320 21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,
91321 21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,
91322 21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,
91323 21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,
91324 21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,
91325 21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,
91326 21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,
91327 21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,
91328 21143,21144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,
91329 21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,
91330 21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,
91331 21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,
91332 21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,
91333 21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,
91334 21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,
91335 21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,
91336 21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,
91337 21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,
91338 21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,
91339 21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,
91340 21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,
91341 21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21310,
91342 21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,
91343 21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,
91344 21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,
91345 21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,
91346 21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,
91347 21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,
91348 21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,
91349 21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,
91350 21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,
91351 21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,
91352 21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,
91353 21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,
91354 21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,
91355 21467,21468,21469,21470,21471,21472,21473,21474,21475,21476,21477,21478,
91356 21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,
91357 21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,
91358 21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,
91359 21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,
91360 21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,
91361 21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,
91362 21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,
91363 21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,
91364 21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,
91365 21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,
91366 21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,
91367 21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,
91368 21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,
91369 21635,21636,21637,21638,21639,21640,21641,21642,21643,21644,21645,21646,
91370 21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,
91371 21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,
91372 21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,
91373 21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,
91374 21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,
91375 21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,
91376 21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,
91377 21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,
91378 21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,
91379 21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,
91380 21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,
91381 21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,
91382 21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,
91383 21803,21804,21805,21806,21807,21808,21809,21810,21811,21812,21813,21814,
91384 21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,
91385 21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,
91386 21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,
91387 21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,
91388 21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,
91389 21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,
91390 21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,
91391 21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,
91392 21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,
91393 21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,
91394 21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,
91395 21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,
91396 21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,
91397 21971,21972,21973,21974,21975,21976,21977,21978,21979,21980,21981,21982,
91398 21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,
91399 21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,
91400 22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,
91401 22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,
91402 22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,
91403 22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,
91404 22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,
91405 22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,
91406 22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,
91407 22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,
91408 22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,
91409 22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,
91410 22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,
91411 22139,22140,22141,22142,22143,22144,22145,22146,22147,22148,22149,22150,
91412 22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,
91413 22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,
91414 22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,
91415 22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,
91416 22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,
91417 22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,
91418 22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,
91419 22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,
91420 22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,
91421 22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,
91422 22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,
91423 22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,
91424 22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,
91425 22307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,
91426 22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,
91427 22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,
91428 22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,
91429 22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,
91430 22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,
91431 22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,
91432 22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,
91433 22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,
91434 22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,
91435 22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,
91436 22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,
91437 22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,
91438 22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,22473,22474,
91439 22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,
91440 22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,
91441 22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,
91442 22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,
91443 22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,
91444 22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,
91445 22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,
91446 22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,
91447 22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,
91448 22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,
91449 22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,
91450 22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,
91451 22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,
91452 22631,22632,22633,22634,22635,22636,22637,22638,22639,22640,22641,22642,
91453 22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,
91454 22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,
91455 22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,
91456 22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,
91457 22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,
91458 22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,
91459 22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,
91460 22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,
91461 22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,
91462 22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,
91463 22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,
91464 22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,
91465 22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,
91466 22799,22800,22801,22802,22803,22804,22805,22806,22807,22808,22809,22810,
91467 22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,
91468 22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,
91469 22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,
91470 22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,
91471 22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,
91472 22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,
91473 22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,
91474 22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,
91475 22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,
91476 22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,
91477 22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,
91478 22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,
91479 22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,
91480 22967,22968,22969,22970,22971,22972,22973,22974,22975,22976,22977,22978,
91481 22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,
91482 22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,
91483 23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,
91484 23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,
91485 23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,
91486 23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,
91487 23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,
91488 23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,
91489 23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,
91490 23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,
91491 23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,
91492 23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,
91493 23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,
91494 23135,23136,23137,23138,23139,23140,23141,23142,23143,23144,23145,23146,
91495 23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,
91496 23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,
91497 23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,
91498 23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,
91499 23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,
91500 23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,
91501 23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,
91502 23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,
91503 23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,
91504 23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,
91505 23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,
91506 23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,
91507 23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,
91508 23303,23304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,
91509 23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,
91510 23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,
91511 23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,
91512 23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,
91513 23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,
91514 23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,
91515 23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,
91516 23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,
91517 23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,
91518 23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,
91519 23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,
91520 23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,
91521 23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,23470,
91522 23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,
91523 23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,
91524 23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,
91525 23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,
91526 23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,
91527 23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,
91528 23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,
91529 23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,
91530 23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,
91531 23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,
91532 23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,
91533 23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,
91534 23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,
91535 23627,23628,23629,23630,23631,23632,23633,23634,23635,23636,23637,23638,
91536 23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,
91537 23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,
91538 23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,
91539 23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,
91540 23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,
91541 23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,
91542 23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,
91543 23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,
91544 23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,
91545 23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,
91546 23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,
91547 23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,
91548 23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,
91549 23795,23796,23797,23798,23799,23800,23801,23802,23803,23804,23805,23806,
91550 23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,
91551 23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,
91552 23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,
91553 23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,
91554 23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,
91555 23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,
91556 23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,
91557 23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,
91558 23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,
91559 23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,
91560 23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,
91561 23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,
91562 23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,
91563 23963,23964,23965,23966,23967,23968,23969,23970,23971,23972,23973,23974,
91564 23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,
91565 23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,
91566 23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,
91567 24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,
91568 24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,
91569 24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,
91570 24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,
91571 24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,
91572 24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,
91573 24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,
91574 24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,
91575 24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,
91576 24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,
91577 24131,24132,24133,24134,24135,24136,24137,24138,24139,24140,24141,24142,
91578 24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,
91579 24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,
91580 24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,
91581 24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,
91582 24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,
91583 24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,
91584 24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,
91585 24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,
91586 24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,
91587 24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,
91588 24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,
91589 24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,
91590 24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,
91591 24299,24300,24301,24302,24303,24304,24305,24306,24307,24308,24309,24310,
91592 24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,
91593 24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,
91594 24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,
91595 24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,
91596 24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,
91597 24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,
91598 24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,
91599 24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,
91600 24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,
91601 24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,
91602 24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,
91603 24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,
91604 24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,
91605 24467,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,
91606 24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,
91607 24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,
91608 24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,
91609 24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,
91610 24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,
91611 24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,
91612 24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,
91613 24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,
91614 24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,
91615 24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,
91616 24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,
91617 24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,
91618 24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,24633,24634,
91619 24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,
91620 24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,
91621 24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,
91622 24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,
91623 24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,
91624 24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,
91625 24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,
91626 24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,
91627 24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,
91628 24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,
91629 24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,
91630 24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,
91631 24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,
91632 24791,24792,24793,24794,24795,24796,24797,24798,24799,24800,24801,24802,
91633 24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,
91634 24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,
91635 24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,
91636 24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,
91637 24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,
91638 24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,
91639 24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,
91640 24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,
91641 24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,
91642 24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,
91643 24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,
91644 24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,
91645 24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,
91646 24959,24960,24961,24962,24963,24964,24965,24966,24967,24968,24969,24970,
91647 24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,
91648 24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,
91649 24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,
91650 25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,
91651 25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,
91652 25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,
91653 25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,
91654 25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,
91655 25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,
91656 25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,
91657 25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,
91658 25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,
91659 25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,
91660 25127,25128,25129,25130,25131,25132,25133,25134,25135,25136,25137,25138,
91661 25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,
91662 25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,
91663 25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,
91664 25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,
91665 25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,
91666 25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,
91667 25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,
91668 25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,
91669 25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,
91670 25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,
91671 25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,
91672 25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,
91673 25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,
91674 25295,25296,25297,25298,25299,25300,25301,25302,25303,25304,25305,25306,
91675 25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,
91676 25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,
91677 25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,
91678 25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,
91679 25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,
91680 25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,
91681 25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,
91682 25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,
91683 25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,
91684 25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,
91685 25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,
91686 25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,
91687 25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,
91688 25463,25464,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,
91689 25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,
91690 25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,
91691 25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,
91692 25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,
91693 25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,
91694 25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,
91695 25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,
91696 25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,
91697 25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,
91698 25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,
91699 25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,
91700 25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,
91701 25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,25630,
91702 25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,
91703 25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,
91704 25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,
91705 25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,
91706 25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,
91707 25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,
91708 25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,
91709 25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,
91710 25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,
91711 25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,
91712 25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,
91713 25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,
91714 25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,
91715 25787,25788,25789,25790,25791,25792,25793,25794,25795,25796,25797,25798,
91716 25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,
91717 25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,
91718 25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,
91719 25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,
91720 25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,
91721 25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,
91722 25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,
91723 25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,
91724 25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,
91725 25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,
91726 25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,
91727 25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,
91728 25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,
91729 25955,25956,25957,25958,25959,25960,25961,25962,25963,25964,25965,25966,
91730 25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,
91731 25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,
91732 25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,
91733 26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,
91734 26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,
91735 26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,
91736 26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,
91737 26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,
91738 26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,
91739 26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,
91740 26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,
91741 26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,
91742 26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,
91743 26123,26124,26125,26126,26127,26128,26129,26130,26131,26132,26133,26134,
91744 26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,
91745 26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,
91746 26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,
91747 26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,
91748 26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,
91749 26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,
91750 26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,
91751 26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,
91752 26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,
91753 26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,
91754 26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,
91755 26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,
91756 26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,
91757 26291,26292,26293,26294,26295,26296,26297,26298,26299,26300,26301,26302,
91758 26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,
91759 26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,
91760 26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,
91761 26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,
91762 26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,
91763 26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,
91764 26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,
91765 26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,
91766 26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,
91767 26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,
91768 26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,
91769 26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,
91770 26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,
91771 26459,26460,26461,26462,26463,26464,26465,26466,26467,26468,26469,26470,
91772 26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,
91773 26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,
91774 26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,
91775 26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,
91776 26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,
91777 26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,
91778 26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,
91779 26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,
91780 26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,
91781 26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,
91782 26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,
91783 26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,
91784 26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,
91785 26627,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,
91786 26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,
91787 26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,
91788 26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,
91789 26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,
91790 26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,
91791 26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,
91792 26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,
91793 26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,
91794 26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,
91795 26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,
91796 26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,
91797 26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,
91798 26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793,26794,
91799 26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,
91800 26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,
91801 26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,
91802 26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,
91803 26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,
91804 26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,
91805 26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,
91806 26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,
91807 26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,
91808 26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,
91809 26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,
91810 26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,
91811 26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,
91812 26951,26952,26953,26954,26955,26956,26957,26958,26959,26960,26961,26962,
91813 26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,
91814 26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,
91815 26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,
91816 26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,
91817 27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,
91818 27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,
91819 27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,
91820 27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,
91821 27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,
91822 27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,
91823 27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,
91824 27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,
91825 27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,
91826 27119,27120,27121,27122,27123,27124,27125,27126,27127,27128,27129,27130,
91827 27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,
91828 27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,
91829 27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,
91830 27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,
91831 27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,
91832 27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,
91833 27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,
91834 27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,
91835 27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,
91836 27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,
91837 27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,
91838 27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,
91839 27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,
91840 27287,27288,27289,27290,27291,27292,27293,27294,27295,27296,27297,27298,
91841 27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,
91842 27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,
91843 27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,
91844 27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,
91845 27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,
91846 27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,
91847 27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,
91848 27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,
91849 27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,
91850 27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,
91851 27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,
91852 27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,
91853 27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,
91854 27455,27456,27457,27458,27459,27460,27461,27462,27463,27464,27465,27466,
91855 27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,
91856 27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,
91857 27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,
91858 27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,
91859 27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,
91860 27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,
91861 27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,
91862 27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,
91863 27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,
91864 27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,
91865 27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,
91866 27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,
91867 27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,
91868 27623,27624,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,
91869 27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,
91870 27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,
91871 27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,
91872 27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,
91873 27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,
91874 27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,
91875 27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,
91876 27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,
91877 27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,
91878 27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,
91879 27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,
91880 27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,
91881 27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790,
91882 27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,
91883 27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,
91884 27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,
91885 27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,
91886 27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,
91887 27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,
91888 27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,
91889 27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,
91890 27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,
91891 27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,
91892 27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,
91893 27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,
91894 27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,
91895 27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,27957,27958,
91896 27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,
91897 27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,
91898 27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,
91899 27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,
91900 28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,
91901 28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,
91902 28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,
91903 28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,
91904 28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,
91905 28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,
91906 28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,
91907 28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,
91908 28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,
91909 28115,28116,28117,28118,28119,28120,28121,28122,28123,28124,28125,28126,
91910 28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,
91911 28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,
91912 28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,
91913 28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,
91914 28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,
91915 28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,
91916 28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,
91917 28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,
91918 28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,
91919 28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,
91920 28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,
91921 28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,
91922 28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,
91923 28283,28284,28285,28286,28287,28288,28289,28290,28291,28292,28293,28294,
91924 28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,
91925 28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,
91926 28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,
91927 28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,
91928 28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,
91929 28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,
91930 28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,
91931 28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,
91932 28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,
91933 28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,
91934 28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,
91935 28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,
91936 28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,
91937 28451,28452,28453,28454,28455,28456,28457,28458,28459,28460,28461,28462,
91938 28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,
91939 28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,
91940 28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,
91941 28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,
91942 28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,
91943 28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,
91944 28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,
91945 28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,
91946 28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,
91947 28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,
91948 28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,
91949 28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,
91950 28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,
91951 28619,28620,28621,28622,28623,28624,28625,28626,28627,28628,28629,28630,
91952 28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,
91953 28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,
91954 28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,
91955 28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,
91956 28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,
91957 28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,
91958 28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,
91959 28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,
91960 28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,
91961 28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,
91962 28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,
91963 28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,
91964 28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,
91965 28787,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,
91966 28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,
91967 28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,
91968 28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,
91969 28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,
91970 28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,
91971 28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,
91972 28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,
91973 28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,
91974 28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,
91975 28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,
91976 28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,
91977 28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,
91978 28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,28954,
91979 28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,
91980 28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,
91981 28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,
91982 28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,
91983 29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,
91984 29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,
91985 29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,
91986 29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,
91987 29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,
91988 29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,
91989 29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,
91990 29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,
91991 29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,
91992 29111,29112,29113,29114,29115,29116,29117,29118,29119,29120,29121,29122,
91993 29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,
91994 29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,
91995 29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,
91996 29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,
91997 29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,
91998 29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,
91999 29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,
92000 29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,
92001 29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,
92002 29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,
92003 29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,
92004 29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,
92005 29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,
92006 29279,29280,29281,29282,29283,29284,29285,29286,29287,29288,29289,29290,
92007 29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,
92008 29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,
92009 29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,
92010 29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,
92011 29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,
92012 29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,
92013 29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,
92014 29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,
92015 29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,
92016 29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,
92017 29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,
92018 29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,
92019 29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,
92020 29447,29448,29449,29450,29451,29452,29453,29454,29455,29456,29457,29458,
92021 29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,
92022 29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,
92023 29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,
92024 29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,
92025 29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,
92026 29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,
92027 29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,
92028 29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,
92029 29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,
92030 29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,
92031 29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,
92032 29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,
92033 29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,
92034 29615,29616,29617,29618,29619,29620,29621,29622,29623,29624,29625,29626,
92035 29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,
92036 29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,
92037 29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,
92038 29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,
92039 29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,
92040 29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,
92041 29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,
92042 29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,
92043 29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,
92044 29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,
92045 29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,
92046 29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,
92047 29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,
92048 29783,29784,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,
92049 29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,
92050 29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,
92051 29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,
92052 29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,
92053 29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,
92054 29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,
92055 29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,
92056 29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,
92057 29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,
92058 29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,
92059 29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,
92060 29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,
92061 29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,
92062 29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,
92063 29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,
92064 29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,
92065 29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,
92066 29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,
92067 30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,
92068 30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,
92069 30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,
92070 30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,
92071 30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,
92072 30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,
92073 30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,
92074 30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,
92075 30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,30117,30118,
92076 30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,
92077 30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,
92078 30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,
92079 30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,
92080 30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,
92081 30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,
92082 30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,
92083 30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,
92084 30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,
92085 30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,
92086 30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,
92087 30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,
92088 30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,
92089 30275,30276,30277,30278,30279,30280,30281,30282,30283,30284,30285,30286,
92090 30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,
92091 30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,
92092 30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,
92093 30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,
92094 30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,
92095 30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,
92096 30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,
92097 30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,
92098 30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,
92099 30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,
92100 30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,
92101 30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,
92102 30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,
92103 30443,30444,30445,30446,30447,30448,30449,30450,30451,30452,30453,30454,
92104 30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,
92105 30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,
92106 30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,
92107 30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,
92108 30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,
92109 30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,
92110 30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,
92111 30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,
92112 30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,
92113 30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,
92114 30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,
92115 30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,
92116 30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,
92117 30611,30612,30613,30614,30615,30616,30617,30618,30619,30620,30621,30622,
92118 30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,
92119 30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,
92120 30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,
92121 30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,
92122 30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,
92123 30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,
92124 30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,
92125 30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,
92126 30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,
92127 30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,
92128 30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,
92129 30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,
92130 30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,
92131 30779,30780,30781,30782,30783,30784,30785,30786,30787,30788,30789,30790,
92132 30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,
92133 30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,
92134 30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,
92135 30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,
92136 30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,
92137 30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,
92138 30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,
92139 30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,
92140 30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,
92141 30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,
92142 30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,
92143 30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,
92144 30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,
92145 30947,30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,
92146 30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,
92147 30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,
92148 30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,
92149 30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,
92150 31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,
92151 31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,
92152 31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,
92153 31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,
92154 31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,
92155 31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,
92156 31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,
92157 31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,
92158 31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,31114,
92159 31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,
92160 31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,
92161 31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,
92162 31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,
92163 31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,
92164 31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,
92165 31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,
92166 31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,
92167 31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,
92168 31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,
92169 31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,
92170 31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,
92171 31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,
92172 31271,31272,31273,31274,31275,31276,31277,31278,31279,31280,31281,31282,
92173 31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,
92174 31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,
92175 31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,
92176 31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,
92177 31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,
92178 31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,
92179 31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,
92180 31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,
92181 31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,
92182 31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,
92183 31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,
92184 31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,
92185 31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,
92186 31439,31440,31441,31442,31443,31444,31445,31446,31447,31448,31449,31450,
92187 31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,
92188 31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,
92189 31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,
92190 31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,
92191 31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,
92192 31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,
92193 31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,
92194 31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,
92195 31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,
92196 31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,
92197 31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,
92198 31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,
92199 31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,
92200 31607,31608,31609,31610,31611,31612,31613,31614,31615,31616,31617,31618,
92201 31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,
92202 31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,
92203 31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,
92204 31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,
92205 31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,
92206 31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,
92207 31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,
92208 31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,
92209 31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,
92210 31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,
92211 31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,
92212 31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,
92213 31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,
92214 31775,31776,31777,31778,31779,31780,31781,31782,31783,31784,31785,31786,
92215 31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,
92216 31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,
92217 31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,
92218 31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,
92219 31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,
92220 31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,
92221 31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,
92222 31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,
92223 31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,
92224 31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,
92225 31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,
92226 31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,
92227 31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,
92228 31943,31944,31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,
92229 31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,
92230 31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,
92231 31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,
92232 31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,
92233 32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,
92234 32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,
92235 32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,
92236 32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,
92237 32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,
92238 32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,
92239 32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,
92240 32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,
92241 32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,
92242 32111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,
92243 32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,
92244 32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,
92245 32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,
92246 32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,
92247 32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,
92248 32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,
92249 32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,
92250 32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,
92251 32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,
92252 32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,
92253 32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,
92254 32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,
92255 32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32277,32278,
92256 32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,
92257 32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,
92258 32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,
92259 32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,
92260 32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,
92261 32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,
92262 32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,
92263 32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,
92264 32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,
92265 32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,
92266 32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,
92267 32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,
92268 32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,
92269 32435,32436,32437,32438,32439,32440,32441,32442,32443,32444,32445,32446,
92270 32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,
92271 32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,
92272 32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,
92273 32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,
92274 32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,
92275 32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,
92276 32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,
92277 32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,
92278 32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,
92279 32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,
92280 32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,
92281 32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,
92282 32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,
92283 32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,
92284 32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,
92285 32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,
92286 32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,
92287 32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,
92288 32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,
92289 32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,
92290 32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,
92291 32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,
92292 32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,
92293 32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,
92294 32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,
92295 32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,
92296 32759,32760,32761,32762,32763,32764,32765,32766,32767,32768L,32769L,32770L,
92297 32771L,32772L,32773L,32774L,32775L,32776L,32777L,32778L,32779L,32780L,
92298 32781L,32782L,32783L,32784L,32785L,32786L,32787L,32788L,32789L,32790L,
92299 32791L,32792L,32793L,32794L,32795L,32796L,32797L,32798L,32799L,32800L,
92300 32801L,32802L,32803L,32804L,32805L,32806L,32807L,32808L,32809L,32810L,
92301 32811L,32812L,32813L,32814L,32815L,32816L,32817L,32818L,32819L,32820L,
92302 32821L,32822L,32823L,32824L,32825L,32826L,32827L,32828L,32829L,32830L,
92303 32831L,32832L,32833L,32834L,32835L,32836L,32837L,32838L,32839L,32840L,
92304 32841L,32842L,32843L,32844L,32845L,32846L,32847L,32848L,32849L,32850L,
92305 32851L,32852L,32853L,32854L,32855L,32856L,32857L,32858L,32859L,32860L,
92306 32861L,32862L,32863L,32864L,32865L,32866L,32867L,32868L,32869L,32870L,
92307 32871L,32872L,32873L,32874L,32875L,32876L,32877L,32878L,32879L,32880L,
92308 32881L,32882L,32883L,32884L,32885L,32886L,32887L,32888L,32889L,32890L,
92309 32891L,32892L,32893L,32894L,32895L,32896L,32897L,32898L,32899L,32900L,
92310 32901L,32902L,32903L,32904L,32905L,32906L,32907L,32908L,32909L,32910L,
92311 32911L,32912L,32913L,32914L,32915L,32916L,32917L,32918L,32919L,32920L,
92312 32921L,32922L,32923L,32924L,32925L,32926L,32927L,32928L,32929L,32930L,
92313 32931L,32932L,32933L,32934L,32935L,32936L,32937L,32938L,32939L,32940L,
92314 32941L,32942L,32943L,32944L,32945L,32946L,32947L,32948L,32949L,32950L,
92315 32951L,32952L,32953L,32954L,32955L,32956L,32957L,32958L,32959L,32960L,
92316 32961L,32962L,32963L,32964L,32965L,32966L,32967L,32968L,32969L,32970L,
92317 32971L,32972L,32973L,32974L,32975L,32976L,32977L,32978L,32979L,32980L,
92318 32981L,32982L,32983L,32984L,32985L,32986L,32987L,32988L,32989L,32990L,
92319 32991L,32992L,32993L,32994L,32995L,32996L,32997L,32998L,32999L,33000L,
92320 33001L,33002L,33003L,33004L,33005L,33006L,33007L,33008L,33009L,33010L,
92321 33011L,33012L,33013L,33014L,33015L,33016L,33017L,33018L,33019L,33020L,
92322 33021L,33022L,33023L,33024L,33025L,33026L,33027L,33028L,33029L,33030L,
92323 33031L,33032L,33033L,33034L,33035L,33036L,33037L,33038L,33039L,33040L,
92324 33041L,33042L,33043L,33044L,33045L,33046L,33047L,33048L,33049L,33050L,
92325 33051L,33052L,33053L,33054L,33055L,33056L,33057L,33058L,33059L,33060L,
92326 33061L,33062L,33063L,33064L,33065L,33066L,33067L,33068L,33069L,33070L,
92327 33071L,33072L,33073L,33074L,33075L,33076L,33077L,33078L,33079L,33080L,
92328 33081L,33082L,33083L,33084L,33085L,33086L,33087L,33088L,33089L,33090L,
92329 33091L,33092L,33093L,33094L,33095L,33096L,33097L,33098L,33099L,33100L,
92330 33101L,33102L,33103L,33104L,33105L,33106L,33107L,33108L,33109L,33110L,
92331 33111L,33112L,33113L,33114L,33115L,33116L,33117L,33118L,33119L,33120L,
92332 33121L,33122L,33123L,33124L,33125L,33126L,33127L,33128L,33129L,33130L,
92333 33131L,33132L,33133L,33134L,33135L,33136L,33137L,33138L,33139L,33140L,
92334 33141L,33142L,33143L,33144L,33145L,33146L,33147L,33148L,33149L,33150L,
92335 33151L,33152L,33153L,33154L,33155L,33156L,33157L,33158L,33159L,33160L,
92336 33161L,33162L,33163L,33164L,33165L,33166L,33167L,33168L,33169L,33170L,
92337 33171L,33172L,33173L,33174L,33175L,33176L,33177L,33178L,33179L,33180L,
92338 33181L,33182L,33183L,33184L,33185L,33186L,33187L,33188L,33189L,33190L,
92339 33191L,33192L,33193L,33194L,33195L,33196L,33197L,33198L,33199L,33200L,
92340 33201L,33202L,33203L,33204L,33205L,33206L,33207L,33208L,33209L,33210L,
92341 33211L,33212L,33213L,33214L,33215L,33216L,33217L,33218L,33219L,33220L,
92342 33221L,33222L,33223L,33224L,33225L,33226L,33227L,33228L,33229L,33230L,
92343 33231L,33232L,33233L,33234L,33235L,33236L,33237L,33238L,33239L,33240L,
92344 33241L,33242L,33243L,33244L,33245L,33246L,33247L,33248L,33249L,33250L,
92345 33251L,33252L,33253L,33254L,33255L,33256L,33257L,33258L,33259L,33260L,
92346 33261L,33262L,33263L,33264L,33265L,33266L,33267L,33268L,33269L,33270L,
92347 33271L,33272L,33273L,33274L,33275L,33276L,33277L,33278L,33279L,33280L,
92348 33281L,33282L,33283L,33284L,33285L,33286L,33287L,33288L,33289L,33290L,
92349 33291L,33292L,33293L,33294L,33295L,33296L,33297L,33298L,33299L,33300L,
92350 33301L,33302L,33303L,33304L,33305L,33306L,33307L,33308L,33309L,33310L,
92351 33311L,33312L,33313L,33314L,33315L,33316L,33317L,33318L,33319L,33320L,
92352 33321L,33322L,33323L,33324L,33325L,33326L,33327L,33328L,33329L,33330L,
92353 33331L,33332L,33333L,33334L,33335L,33336L,33337L,33338L,33339L,33340L,
92354 33341L,33342L,33343L,33344L,33345L,33346L,33347L,33348L,33349L,33350L,
92355 33351L,33352L,33353L,33354L,33355L,33356L,33357L,33358L,33359L,33360L,
92356 33361L,33362L,33363L,33364L,33365L,33366L,33367L,33368L,33369L,33370L,
92357 33371L,33372L,33373L,33374L,33375L,33376L,33377L,33378L,33379L,33380L,
92358 33381L,33382L,33383L,33384L,33385L,33386L,33387L,33388L,33389L,33390L,
92359 33391L,33392L,33393L,33394L,33395L,33396L,33397L,33398L,33399L,33400L,
92360 33401L,33402L,33403L,33404L,33405L,33406L,33407L,33408L,33409L,33410L,
92361 33411L,33412L,33413L,33414L,33415L,33416L,33417L,33418L,33419L,33420L,
92362 33421L,33422L,33423L,33424L,33425L,33426L,33427L,33428L,33429L,33430L,
92363 33431L,33432L,33433L,33434L,33435L,33436L,33437L,33438L,33439L,33440L,
92364 33441L,33442L,33443L,33444L,33445L,33446L,33447L,33448L,33449L,33450L,
92365 33451L,33452L,33453L,33454L,33455L,33456L,33457L,33458L,33459L,33460L,
92366 33461L,33462L,33463L,33464L,33465L,33466L,33467L,33468L,33469L,33470L,
92367 33471L,33472L,33473L,33474L,33475L,33476L,33477L,33478L,33479L,33480L,
92368 33481L,33482L,33483L,33484L,33485L,33486L,33487L,33488L,33489L,33490L,
92369 33491L,33492L,33493L,33494L,33495L,33496L,33497L,33498L,33499L,33500L,
92370 33501L,33502L,33503L,33504L,33505L,33506L,33507L,33508L,33509L,33510L,
92371 33511L,33512L,33513L,33514L,33515L,33516L,33517L,33518L,33519L,33520L,
92372 33521L,33522L,33523L,33524L,33525L,33526L,33527L,33528L,33529L,33530L,
92373 33531L,33532L,33533L,33534L,33535L,33536L,33537L,33538L,33539L,33540L,
92374 33541L,33542L,33543L,33544L,33545L,33546L,33547L,33548L,33549L,33550L,
92375 33551L,33552L,33553L,33554L,33555L,33556L,33557L,33558L,33559L,33560L,
92376 33561L,33562L,33563L,33564L,33565L,33566L,33567L,33568L,33569L,33570L,
92377 33571L,33572L,33573L,33574L,33575L,33576L,33577L,33578L,33579L,33580L,
92378 33581L,33582L,33583L,33584L,33585L,33586L,33587L,33588L,33589L,33590L,
92379 33591L,33592L,33593L,33594L,33595L,33596L,33597L,33598L,33599L,33600L,
92380 33601L,33602L,33603L,33604L,33605L,33606L,33607L,33608L,33609L,33610L,
92381 33611L,33612L,33613L,33614L,33615L,33616L,33617L,33618L,33619L,33620L,
92382 33621L,33622L,33623L,33624L,33625L,33626L,33627L,33628L,33629L,33630L,
92383 33631L,33632L,33633L,33634L,33635L,33636L,33637L,33638L,33639L,33640L,
92384 33641L,33642L,33643L,33644L,33645L,33646L,33647L,33648L,33649L,33650L,
92385 33651L,33652L,33653L,33654L,33655L,33656L,33657L,33658L,33659L,33660L,
92386 33661L,33662L,33663L,33664L,33665L,33666L,33667L,33668L,33669L,33670L,
92387 33671L,33672L,33673L,33674L,33675L,33676L,33677L,33678L,33679L,33680L,
92388 33681L,33682L,33683L,33684L,33685L,33686L,33687L,33688L,33689L,33690L,
92389 33691L,33692L,33693L,33694L,33695L,33696L,33697L,33698L,33699L,33700L,
92390 33701L,33702L,33703L,33704L,33705L,33706L,33707L,33708L,33709L,33710L,
92391 33711L,33712L,33713L,33714L,33715L,33716L,33717L,33718L,33719L,33720L,
92392 33721L,33722L,33723L,33724L,33725L,33726L,33727L,33728L,33729L,33730L,
92393 33731L,33732L,33733L,33734L,33735L,33736L,33737L,33738L,33739L,33740L,
92394 33741L,33742L,33743L,33744L,33745L,33746L,33747L,33748L,33749L,33750L,
92395 33751L,33752L,33753L,33754L,33755L,33756L,33757L,33758L,33759L,33760L,
92396 33761L,33762L,33763L,33764L,33765L,33766L,33767L,33768L,33769L,33770L,
92397 33771L,33772L,33773L,33774L,33775L,33776L,33777L,33778L,33779L,33780L,
92398 33781L,33782L,33783L,33784L,33785L,33786L,33787L,33788L,33789L,33790L,
92399 33791L,33792L,33793L,33794L,33795L,33796L,33797L,33798L,33799L,33800L,
92400 33801L,33802L,33803L,33804L,33805L,33806L,33807L,33808L,33809L,33810L,
92401 33811L,33812L,33813L,33814L,33815L,33816L,33817L,33818L,33819L,33820L,
92402 33821L,33822L,33823L,33824L,33825L,33826L,33827L,33828L,33829L,33830L,
92403 33831L,33832L,33833L,33834L,33835L,33836L,33837L,33838L,33839L,33840L,
92404 33841L,33842L,33843L,33844L,33845L,33846L,33847L,33848L,33849L,33850L,
92405 33851L,33852L,33853L,33854L,33855L,33856L,33857L,33858L,33859L,33860L,
92406 33861L,33862L,33863L,33864L,33865L,33866L,33867L,33868L,33869L,33870L,
92407 33871L,33872L,33873L,33874L,33875L,33876L,33877L,33878L,33879L,33880L,
92408 33881L,33882L,33883L,33884L,33885L,33886L,33887L,33888L,33889L,33890L,
92409 33891L,33892L,33893L,33894L,33895L,33896L,33897L,33898L,33899L,33900L,
92410 33901L,33902L,33903L,33904L,33905L,33906L,33907L,33908L,33909L,33910L,
92411 33911L,33912L,33913L,33914L,33915L,33916L,33917L,33918L,33919L,33920L,
92412 33921L,33922L,33923L,33924L,33925L,33926L,33927L,33928L,33929L,33930L,
92413 33931L,33932L,33933L,33934L,33935L,33936L,33937L,33938L,33939L,33940L,
92414 33941L,33942L,33943L,33944L,33945L,33946L,33947L,33948L,33949L,33950L,
92415 33951L,33952L,33953L,33954L,33955L,33956L,33957L,33958L,33959L,33960L,
92416 33961L,33962L,33963L,33964L,33965L,33966L,33967L,33968L,33969L,33970L,
92417 33971L,33972L,33973L,33974L,33975L,33976L,33977L,33978L,33979L,33980L,
92418 33981L,33982L,33983L,33984L,33985L,33986L,33987L,33988L,33989L,33990L,
92419 33991L,33992L,33993L,33994L,33995L,33996L,33997L,33998L,33999L,34000L,
92420 34001L,34002L,34003L,34004L,34005L,34006L,34007L,34008L,34009L,34010L,
92421 34011L,34012L,34013L,34014L,34015L,34016L,34017L,34018L,34019L,34020L,
92422 34021L,34022L,34023L,34024L,34025L,34026L,34027L,34028L,34029L,34030L,
92423 34031L,34032L,34033L,34034L,34035L,34036L,34037L,34038L,34039L,34040L,
92424 34041L,34042L,34043L,34044L,34045L,34046L,34047L,34048L,34049L,34050L,
92425 34051L,34052L,34053L,34054L,34055L,34056L,34057L,34058L,34059L,34060L,
92426 34061L,34062L,34063L,34064L,34065L,34066L,34067L,34068L,34069L,34070L,
92427 34071L,34072L,34073L,34074L,34075L,34076L,34077L,34078L,34079L,34080L,
92428 34081L,34082L,34083L,34084L,34085L,34086L,34087L,34088L,34089L,34090L,
92429 34091L,34092L,34093L,34094L,34095L,34096L,34097L,34098L,34099L,34100L,
92430 34101L,34102L,34103L,34104L,34105L,34106L,34107L,34108L,34109L,34110L,
92431 34111L,34112L,34113L,34114L,34115L,34116L,34117L,34118L,34119L,34120L,
92432 34121L,34122L,34123L,34124L,34125L,34126L,34127L,34128L,34129L,34130L,
92433 34131L,34132L,34133L,34134L,34135L,34136L,34137L,34138L,34139L,34140L,
92434 34141L,34142L,34143L,34144L,34145L,34146L,34147L,34148L,34149L,34150L,
92435 34151L,34152L,34153L,34154L,34155L,34156L,34157L,34158L,34159L,34160L,
92436 34161L,34162L,34163L,34164L,34165L,34166L,34167L,34168L,34169L,34170L,
92437 34171L,34172L,34173L,34174L,34175L,34176L,34177L,34178L,34179L,34180L,
92438 34181L,34182L,34183L,34184L,34185L,34186L,34187L,34188L,34189L,34190L,
92439 34191L,34192L,34193L,34194L,34195L,34196L,34197L,34198L,34199L,34200L,
92440 34201L,34202L,34203L,34204L,34205L,34206L,34207L,34208L,34209L,34210L,
92441 34211L,34212L,34213L,34214L,34215L,34216L,34217L,34218L,34219L,34220L,
92442 34221L,34222L,34223L,34224L,34225L,34226L,34227L,34228L,34229L,34230L,
92443 34231L,34232L,34233L,34234L,34235L,34236L,34237L,34238L,34239L,34240L,
92444 34241L,34242L,34243L,34244L,34245L,34246L,34247L,34248L,34249L,34250L,
92445 34251L,34252L,34253L,34254L,34255L,34256L,34257L,34258L,34259L,34260L,
92446 34261L,34262L,34263L,34264L,34265L,34266L,34267L,34268L,34269L,34270L,
92447 34271L,34272L,34273L,34274L,34275L,34276L,34277L,34278L,34279L,34280L,
92448 34281L,34282L,34283L,34284L,34285L,34286L,34287L,34288L,34289L,34290L,
92449 34291L,34292L,34293L,34294L,34295L,34296L,34297L,34298L,34299L,34300L,
92450 34301L,34302L,34303L,34304L,34305L,34306L,34307L,34308L,34309L,34310L,
92451 34311L,34312L,34313L,34314L,34315L,34316L,34317L,34318L,34319L,34320L,
92452 34321L,34322L,34323L,34324L,34325L,34326L,34327L,34328L,34329L,34330L,
92453 34331L,34332L,34333L,34334L,34335L,34336L,34337L,34338L,34339L,34340L,
92454 34341L,34342L,34343L,34344L,34345L,34346L,34347L,34348L,34349L,34350L,
92455 34351L,34352L,34353L,34354L,34355L,34356L,34357L,34358L,34359L,34360L,
92456 34361L,34362L,34363L,34364L,34365L,34366L,34367L,34368L,34369L,34370L,
92457 34371L,34372L,34373L,34374L,34375L,34376L,34377L,34378L,34379L,34380L,
92458 34381L,34382L,34383L,34384L,34385L,34386L,34387L,34388L,34389L,34390L,
92459 34391L,34392L,34393L,34394L,34395L,34396L,34397L,34398L,34399L,34400L,
92460 34401L,34402L,34403L,34404L,34405L,34406L,34407L,34408L,34409L,34410L,
92461 34411L,34412L,34413L,34414L,34415L,34416L,34417L,34418L,34419L,34420L,
92462 34421L,34422L,34423L,34424L,34425L,34426L,34427L,34428L,34429L,34430L,
92463 34431L,34432L,34433L,34434L,34435L,34436L,34437L,34438L,34439L,34440L,
92464 34441L,34442L,34443L,34444L,34445L,34446L,34447L,34448L,34449L,34450L,
92465 34451L,34452L,34453L,34454L,34455L,34456L,34457L,34458L,34459L,34460L,
92466 34461L,34462L,34463L,34464L,34465L,34466L,34467L,34468L,34469L,34470L,
92467 34471L,34472L,34473L,34474L,34475L,34476L,34477L,34478L,34479L,34480L,
92468 34481L,34482L,34483L,34484L,34485L,34486L,34487L,34488L,34489L,34490L,
92469 34491L,34492L,34493L,34494L,34495L,34496L,34497L,34498L,34499L,34500L,
92470 34501L,34502L,34503L,34504L,34505L,34506L,34507L,34508L,34509L,34510L,
92471 34511L,34512L,34513L,34514L,34515L,34516L,34517L,34518L,34519L,34520L,
92472 34521L,34522L,34523L,34524L,34525L,34526L,34527L,34528L,34529L,34530L,
92473 34531L,34532L,34533L,34534L,34535L,34536L,34537L,34538L,34539L,34540L,
92474 34541L,34542L,34543L,34544L,34545L,34546L,34547L,34548L,34549L,34550L,
92475 34551L,34552L,34553L,34554L,34555L,34556L,34557L,34558L,34559L,34560L,
92476 34561L,34562L,34563L,34564L,34565L,34566L,34567L,34568L,34569L,34570L,
92477 34571L,34572L,34573L,34574L,34575L,34576L,34577L,34578L,34579L,34580L,
92478 34581L,34582L,34583L,34584L,34585L,34586L,34587L,34588L,34589L,34590L,
92479 34591L,34592L,34593L,34594L,34595L,34596L,34597L,34598L,34599L,34600L,
92480 34601L,34602L,34603L,34604L,34605L,34606L,34607L,34608L,34609L,34610L,
92481 34611L,34612L,34613L,34614L,34615L,34616L,34617L,34618L,34619L,34620L,
92482 34621L,34622L,34623L,34624L,34625L,34626L,34627L,34628L,34629L,34630L,
92483 34631L,34632L,34633L,34634L,34635L,34636L,34637L,34638L,34639L,34640L,
92484 34641L,34642L,34643L,34644L,34645L,34646L,34647L,34648L,34649L,34650L,
92485 34651L,34652L,34653L,34654L,34655L,34656L,34657L,34658L,34659L,34660L,
92486 34661L,34662L,34663L,34664L,34665L,34666L,34667L,34668L,34669L,34670L,
92487 34671L,34672L,34673L,34674L,34675L,34676L,34677L,34678L,34679L,34680L,
92488 34681L,34682L,34683L,34684L,34685L,34686L,34687L,34688L,34689L,34690L,
92489 34691L,34692L,34693L,34694L,34695L,34696L,34697L,34698L,34699L,34700L,
92490 34701L,34702L,34703L,34704L,34705L,34706L,34707L,34708L,34709L,34710L,
92491 34711L,34712L,34713L,34714L,34715L,34716L,34717L,34718L,34719L,34720L,
92492 34721L,34722L,34723L,34724L,34725L,34726L,34727L,34728L,34729L,34730L,
92493 34731L,34732L,34733L,34734L,34735L,34736L,34737L,34738L,34739L,34740L,
92494 34741L,34742L,34743L,34744L,34745L,34746L,34747L,34748L,34749L,34750L,
92495 34751L,34752L,34753L,34754L,34755L,34756L,34757L,34758L,34759L,34760L,
92496 34761L,34762L,34763L,34764L,34765L,34766L,34767L,34768L,34769L,34770L,
92497 34771L,34772L,34773L,34774L,34775L,34776L,34777L,34778L,34779L,34780L,
92498 34781L,34782L,34783L,34784L,34785L,34786L,34787L,34788L,34789L,34790L,
92499 34791L,34792L,34793L,34794L,34795L,34796L,34797L,34798L,34799L,34800L,
92500 34801L,34802L,34803L,34804L,34805L,34806L,34807L,34808L,34809L,34810L,
92501 34811L,34812L,34813L,34814L,34815L,34816L,34817L,34818L,34819L,34820L,
92502 34821L,34822L,34823L,34824L,34825L,34826L,34827L,34828L,34829L,34830L,
92503 34831L,34832L,34833L,34834L,34835L,34836L,34837L,34838L,34839L,34840L,
92504 34841L,34842L,34843L,34844L,34845L,34846L,34847L,34848L,34849L,34850L,
92505 34851L,34852L,34853L,34854L,34855L,34856L,34857L,34858L,34859L,34860L,
92506 34861L,34862L,34863L,34864L,34865L,34866L,34867L,34868L,34869L,34870L,
92507 34871L,34872L,34873L,34874L,34875L,34876L,34877L,34878L,34879L,34880L,
92508 34881L,34882L,34883L,34884L,34885L,34886L,34887L,34888L,34889L,34890L,
92509 34891L,34892L,34893L,34894L,34895L,34896L,34897L,34898L,34899L,34900L,
92510 34901L,34902L,34903L,34904L,34905L,34906L,34907L,34908L,34909L,34910L,
92511 34911L,34912L,34913L,34914L,34915L,34916L,34917L,34918L,34919L,34920L,
92512 34921L,34922L,34923L,34924L,34925L,34926L,34927L,34928L,34929L,34930L,
92513 34931L,34932L,34933L,34934L,34935L,34936L,34937L,34938L,34939L,34940L,
92514 34941L,34942L,34943L,34944L,34945L,34946L,34947L,34948L,34949L,34950L,
92515 34951L,34952L,34953L,34954L,34955L,34956L,34957L,34958L,34959L,34960L,
92516 34961L,34962L,34963L,34964L,34965L,34966L,34967L,34968L,34969L,34970L,
92517 34971L,34972L,34973L,34974L,34975L,34976L,34977L,34978L,34979L,34980L,
92518 34981L,34982L,34983L,34984L,34985L,34986L,34987L,34988L,34989L,34990L,
92519 34991L,34992L,34993L,34994L,34995L,34996L,34997L,34998L,34999L,35000L,
92520 35001L,35002L,35003L,35004L,35005L,35006L,35007L,35008L,35009L,35010L,
92521 35011L,35012L,35013L,35014L,35015L,35016L,35017L,35018L,35019L,35020L,
92522 35021L,35022L,35023L,35024L,35025L,35026L,35027L,35028L,35029L,35030L,
92523 35031L,35032L,35033L,35034L,35035L,35036L,35037L,35038L,35039L,35040L,
92524 35041L,35042L,35043L,35044L,35045L,35046L,35047L,35048L,35049L,35050L,
92525 35051L,35052L,35053L,35054L,35055L,35056L,35057L,35058L,35059L,35060L,
92526 35061L,35062L,35063L,35064L,35065L,35066L,35067L,35068L,35069L,35070L,
92527 35071L,35072L,35073L,35074L,35075L,35076L,35077L,35078L,35079L,35080L,
92528 35081L,35082L,35083L,35084L,35085L,35086L,35087L,35088L,35089L,35090L,
92529 35091L,35092L,35093L,35094L,35095L,35096L,35097L,35098L,35099L,35100L,
92530 35101L,35102L,35103L,35104L,35105L,35106L,35107L,35108L,35109L,35110L,
92531 35111L,35112L,35113L,35114L,35115L,35116L,35117L,35118L,35119L,35120L,
92532 35121L,35122L,35123L,35124L,35125L,35126L,35127L,35128L,35129L,35130L,
92533 35131L,35132L,35133L,35134L,35135L,35136L,35137L,35138L,35139L,35140L,
92534 35141L,35142L,35143L,35144L,35145L,35146L,35147L,35148L,35149L,35150L,
92535 35151L,35152L,35153L,35154L,35155L,35156L,35157L,35158L,35159L,35160L,
92536 35161L,35162L,35163L,35164L,35165L,35166L,35167L,35168L,35169L,35170L,
92537 35171L,35172L,35173L,35174L,35175L,35176L,35177L,35178L,35179L,35180L,
92538 35181L,35182L,35183L,35184L,35185L,35186L,35187L,35188L,35189L,35190L,
92539 35191L,35192L,35193L,35194L,35195L,35196L,35197L,35198L,35199L,35200L,
92540 35201L,35202L,35203L,35204L,35205L,35206L,35207L,35208L,35209L,35210L,
92541 35211L,35212L,35213L,35214L,35215L,35216L,35217L,35218L,35219L,35220L,
92542 35221L,35222L,35223L,35224L,35225L,35226L,35227L,35228L,35229L,35230L,
92543 35231L,35232L,35233L,35234L,35235L,35236L,35237L,35238L,35239L,35240L,
92544 35241L,35242L,35243L,35244L,35245L,35246L,35247L,35248L,35249L,35250L,
92545 35251L,35252L,35253L,35254L,35255L,35256L,35257L,35258L,35259L,35260L,
92546 35261L,35262L,35263L,35264L,35265L,35266L,35267L,35268L,35269L,35270L,
92547 35271L,35272L,35273L,35274L,35275L,35276L,35277L,35278L,35279L,35280L,
92548 35281L,35282L,35283L,35284L,35285L,35286L,35287L,35288L,35289L,35290L,
92549 35291L,35292L,35293L,35294L,35295L,35296L,35297L,35298L,35299L,35300L,
92550 35301L,35302L,35303L,35304L,35305L,35306L,35307L,35308L,35309L,35310L,
92551 35311L,35312L,35313L,35314L,35315L,35316L,35317L,35318L,35319L,35320L,
92552 35321L,35322L,35323L,35324L,35325L,35326L,35327L,35328L,35329L,35330L,
92553 35331L,35332L,35333L,35334L,35335L,35336L,35337L,35338L,35339L,35340L,
92554 35341L,35342L,35343L,35344L,35345L,35346L,35347L,35348L,35349L,35350L,
92555 35351L,35352L,35353L,35354L,35355L,35356L,35357L,35358L,35359L,35360L,
92556 35361L,35362L,35363L,35364L,35365L,35366L,35367L,35368L,35369L,35370L,
92557 35371L,35372L,35373L,35374L,35375L,35376L,35377L,35378L,35379L,35380L,
92558 35381L,35382L,35383L,35384L,35385L,35386L,35387L,35388L,35389L,35390L,
92559 35391L,35392L,35393L,35394L,35395L,35396L,35397L,35398L,35399L,35400L,
92560 35401L,35402L,35403L,35404L,35405L,35406L,35407L,35408L,35409L,35410L,
92561 35411L,35412L,35413L,35414L,35415L,35416L,35417L,35418L,35419L,35420L,
92562 35421L,35422L,35423L,35424L,35425L,35426L,35427L,35428L,35429L,35430L,
92563 35431L,35432L,35433L,35434L,35435L,35436L,35437L,35438L,35439L,35440L,
92564 35441L,35442L,35443L,35444L,35445L,35446L,35447L,35448L,35449L,35450L,
92565 35451L,35452L,35453L,35454L,35455L,35456L,35457L,35458L,35459L,35460L,
92566 35461L,35462L,35463L,35464L,35465L,35466L,35467L,35468L,35469L,35470L,
92567 35471L,35472L,35473L,35474L,35475L,35476L,35477L,35478L,35479L,35480L,
92568 35481L,35482L,35483L,35484L,35485L,35486L,35487L,35488L,35489L,35490L,
92569 35491L,35492L,35493L,35494L,35495L,35496L,35497L,35498L,35499L,35500L,
92570 35501L,35502L,35503L,35504L,35505L,35506L,35507L,35508L,35509L,35510L,
92571 35511L,35512L,35513L,35514L,35515L,35516L,35517L,35518L,35519L,35520L,
92572 35521L,35522L,35523L,35524L,35525L,35526L,35527L,35528L,35529L,35530L,
92573 35531L,35532L,35533L,35534L,35535L,35536L,35537L,35538L,35539L,35540L,
92574 35541L,35542L,35543L,35544L,35545L,35546L,35547L,35548L,35549L,35550L,
92575 35551L,35552L,35553L,35554L,35555L,35556L,35557L,35558L,35559L,35560L,
92576 35561L,35562L,35563L,35564L,35565L,35566L,35567L,35568L,35569L,35570L,
92577 35571L,35572L,35573L,35574L,35575L,35576L,35577L,35578L,35579L,35580L,
92578 35581L,35582L,35583L,35584L,35585L,35586L,35587L,35588L,35589L,35590L,
92579 35591L,35592L,35593L,35594L,35595L,35596L,35597L,35598L,35599L,35600L,
92580 35601L,35602L,35603L,35604L,35605L,35606L,35607L,35608L,35609L,35610L,
92581 35611L,35612L,35613L,35614L,35615L,35616L,35617L,35618L,35619L,35620L,
92582 35621L,35622L,35623L,35624L,35625L,35626L,35627L,35628L,35629L,35630L,
92583 35631L,35632L,35633L,35634L,35635L,35636L,35637L,35638L,35639L,35640L,
92584 35641L,35642L,35643L,35644L,35645L,35646L,35647L,35648L,35649L,35650L,
92585 35651L,35652L,35653L,35654L,35655L,35656L,35657L,35658L,35659L,35660L,
92586 35661L,35662L,35663L,35664L,35665L,35666L,35667L,35668L,35669L,35670L,
92587 35671L,35672L,35673L,35674L,35675L,35676L,35677L,35678L,35679L,35680L,
92588 35681L,35682L,35683L,35684L,35685L,35686L,35687L,35688L,35689L,35690L,
92589 35691L,35692L,35693L,35694L,35695L,35696L,35697L,35698L,35699L,35700L,
92590 35701L,35702L,35703L,35704L,35705L,35706L,35707L,35708L,35709L,35710L,
92591 35711L,35712L,35713L,35714L,35715L,35716L,35717L,35718L,35719L,35720L,
92592 35721L,35722L,35723L,35724L,35725L,35726L,35727L,35728L,35729L,35730L,
92593 35731L,35732L,35733L,35734L,35735L,35736L,35737L,35738L,35739L,35740L,
92594 35741L,35742L,35743L,35744L,35745L,35746L,35747L,35748L,35749L,35750L,
92595 35751L,35752L,35753L,35754L,35755L,35756L,35757L,35758L,35759L,35760L,
92596 35761L,35762L,35763L,35764L,35765L,35766L,35767L,35768L,35769L,35770L,
92597 35771L,35772L,35773L,35774L,35775L,35776L,35777L,35778L,35779L,35780L,
92598 35781L,35782L,35783L,35784L,35785L,35786L,35787L,35788L,35789L,35790L,
92599 35791L,35792L,35793L,35794L,35795L,35796L,35797L,35798L,35799L,35800L,
92600 35801L,35802L,35803L,35804L,35805L,35806L,35807L,35808L,35809L,35810L,
92601 35811L,35812L,35813L,35814L,35815L,35816L,35817L,35818L,35819L,35820L,
92602 35821L,35822L,35823L,35824L,35825L,35826L,35827L,35828L,35829L,35830L,
92603 35831L,35832L,35833L,35834L,35835L,35836L,35837L,35838L,35839L,35840L,
92604 35841L,35842L,35843L,35844L,35845L,35846L,35847L,35848L,35849L,35850L,
92605 35851L,35852L,35853L,35854L,35855L,35856L,35857L,35858L,35859L,35860L,
92606 35861L,35862L,35863L,35864L,35865L,35866L,35867L,35868L,35869L,35870L,
92607 35871L,35872L,35873L,35874L,35875L,35876L,35877L,35878L,35879L,35880L,
92608 35881L,35882L,35883L,35884L,35885L,35886L,35887L,35888L,35889L,35890L,
92609 35891L,35892L,35893L,35894L,35895L,35896L,35897L,35898L,35899L,35900L,
92610 35901L,35902L,35903L,35904L,35905L,35906L,35907L,35908L,35909L,35910L,
92611 35911L,35912L,35913L,35914L,35915L,35916L,35917L,35918L,35919L,35920L,
92612 35921L,35922L,35923L,35924L,35925L,35926L,35927L,35928L,35929L,35930L,
92613 35931L,35932L,35933L,35934L,35935L,35936L,35937L,35938L,35939L,35940L,
92614 35941L,35942L,35943L,35944L,35945L,35946L,35947L,35948L,35949L,35950L,
92615 35951L,35952L,35953L,35954L,35955L,35956L,35957L,35958L,35959L,35960L,
92616 35961L,35962L,35963L,35964L,35965L,35966L,35967L,35968L,35969L,35970L,
92617 35971L,35972L,35973L,35974L,35975L,35976L,35977L,35978L,35979L,35980L,
92618 35981L,35982L,35983L,35984L,35985L,35986L,35987L,35988L,35989L,35990L,
92619 35991L,35992L,35993L,35994L,35995L,35996L,35997L,35998L,35999L,36000L,
92620 36001L,36002L,36003L,36004L,36005L,36006L,36007L,36008L,36009L,36010L,
92621 36011L,36012L,36013L,36014L,36015L,36016L,36017L,36018L,36019L,36020L,
92622 36021L,36022L,36023L,36024L,36025L,36026L,36027L,36028L,36029L,36030L,
92623 36031L,36032L,36033L,36034L,36035L,36036L,36037L,36038L,36039L,36040L,
92624 36041L,36042L,36043L,36044L,36045L,36046L,36047L,36048L,36049L,36050L,
92625 36051L,36052L,36053L,36054L,36055L,36056L,36057L,36058L,36059L,36060L,
92626 36061L,36062L,36063L,36064L,36065L,36066L,36067L,36068L,36069L,36070L,
92627 36071L,36072L,36073L,36074L,36075L,36076L,36077L,36078L,36079L,36080L,
92628 36081L,36082L,36083L,36084L,36085L,36086L,36087L,36088L,36089L,36090L,
92629 36091L,36092L,36093L,36094L,36095L,36096L,36097L,36098L,36099L,36100L,
92630 36101L,36102L,36103L,36104L,36105L,36106L,36107L,36108L,36109L,36110L,
92631 36111L,36112L,36113L,36114L,36115L,36116L,36117L,36118L,36119L,36120L,
92632 36121L,36122L,36123L,36124L,36125L,36126L,36127L,36128L,36129L,36130L,
92633 36131L,36132L,36133L,36134L,36135L,36136L,36137L,36138L,36139L,36140L,
92634 36141L,36142L,36143L,36144L,36145L,36146L,36147L,36148L,36149L,36150L,
92635 36151L,36152L,36153L,36154L,36155L,36156L,36157L,36158L,36159L,36160L,
92636 36161L,36162L,36163L,36164L,36165L,36166L,36167L,36168L,36169L,36170L,
92637 36171L,36172L,36173L,36174L,36175L,36176L,36177L,36178L,36179L,36180L,
92638 36181L,36182L,36183L,36184L,36185L,36186L,36187L,36188L,36189L,36190L,
92639 36191L,36192L,36193L,36194L,36195L,36196L,36197L,36198L,36199L,36200L,
92640 36201L,36202L,36203L,36204L,36205L,36206L,36207L,36208L,36209L,36210L,
92641 36211L,36212L,36213L,36214L,36215L,36216L,36217L,36218L,36219L,36220L,
92642 36221L,36222L,36223L,36224L,36225L,36226L,36227L,36228L,36229L,36230L,
92643 36231L,36232L,36233L,36234L,36235L,36236L,36237L,36238L,36239L,36240L,
92644 36241L,36242L,36243L,36244L,36245L,36246L,36247L,36248L,36249L,36250L,
92645 36251L,36252L,36253L,36254L,36255L,36256L,36257L,36258L,36259L,36260L,
92646 36261L,36262L,36263L,36264L,36265L,36266L,36267L,36268L,36269L,36270L,
92647 36271L,36272L,36273L,36274L,36275L,36276L,36277L,36278L,36279L,36280L,
92648 36281L,36282L,36283L,36284L,36285L,36286L,36287L,36288L,36289L,36290L,
92649 36291L,36292L,36293L,36294L,36295L,36296L,36297L,36298L,36299L,36300L,
92650 36301L,36302L,36303L,36304L,36305L,36306L,36307L,36308L,36309L,36310L,
92651 36311L,36312L,36313L,36314L,36315L,36316L,36317L,36318L,36319L,36320L,
92652 36321L,36322L,36323L,36324L,36325L,36326L,36327L,36328L,36329L,36330L,
92653 36331L,36332L,36333L,36334L,36335L,36336L,36337L,36338L,36339L,36340L,
92654 36341L,36342L,36343L,36344L,36345L,36346L,36347L,36348L,36349L,36350L,
92655 36351L,36352L,36353L,36354L,36355L,36356L,36357L,36358L,36359L,36360L,
92656 36361L,36362L,36363L,36364L,36365L,36366L,36367L,36368L,36369L,36370L,
92657 36371L,36372L,36373L,36374L,36375L,36376L,36377L,36378L,36379L,36380L,
92658 36381L,36382L,36383L,36384L,36385L,36386L,36387L,36388L,36389L,36390L,
92659 36391L,36392L,36393L,36394L,36395L,36396L,36397L,36398L,36399L,36400L,
92660 36401L,36402L,36403L,36404L,36405L,36406L,36407L,36408L,36409L,36410L,
92661 36411L,36412L,36413L,36414L,36415L,36416L,36417L,36418L,36419L,36420L,
92662 36421L,36422L,36423L,36424L,36425L,36426L,36427L,36428L,36429L,36430L,
92663 36431L,36432L,36433L,36434L,36435L,36436L,36437L,36438L,36439L,36440L,
92664 36441L,36442L,36443L,36444L,36445L,36446L,36447L,36448L,36449L,36450L,
92665 36451L,36452L,36453L,36454L,36455L,36456L,36457L,36458L,36459L,36460L,
92666 36461L,36462L,36463L,36464L,36465L,36466L,36467L,36468L,36469L,36470L,
92667 36471L,36472L,36473L,36474L,36475L,36476L,36477L,36478L,36479L,36480L,
92668 36481L,36482L,36483L,36484L,36485L,36486L,36487L,36488L,36489L,36490L,
92669 36491L,36492L,36493L,36494L,36495L,36496L,36497L,36498L,36499L,36500L,
92670 36501L,36502L,36503L,36504L,36505L,36506L,36507L,36508L,36509L,36510L,
92671 36511L,36512L,36513L,36514L,36515L,36516L,36517L,36518L,36519L,36520L,
92672 36521L,36522L,36523L,36524L,36525L,36526L,36527L,36528L,36529L,36530L,
92673 36531L,36532L,36533L,36534L,36535L,36536L,36537L,36538L,36539L,36540L,
92674 36541L,36542L,36543L,36544L,36545L,36546L,36547L,36548L,36549L,36550L,
92675 36551L,36552L,36553L,36554L,36555L,36556L,36557L,36558L,36559L,36560L,
92676 36561L,36562L,36563L,36564L,36565L,36566L,36567L,36568L,36569L,36570L,
92677 36571L,36572L,36573L,36574L,36575L,36576L,36577L,36578L,36579L,36580L,
92678 36581L,36582L,36583L,36584L,36585L,36586L,36587L,36588L,36589L,36590L,
92679 36591L,36592L,36593L,36594L,36595L,36596L,36597L,36598L,36599L,36600L,
92680 36601L,36602L,36603L,36604L,36605L,36606L,36607L,36608L,36609L,36610L,
92681 36611L,36612L,36613L,36614L,36615L,36616L,36617L,36618L,36619L,36620L,
92682 36621L,36622L,36623L,36624L,36625L,36626L,36627L,36628L,36629L,36630L,
92683 36631L,36632L,36633L,36634L,36635L,36636L,36637L,36638L,36639L,36640L,
92684 36641L,36642L,36643L,36644L,36645L,36646L,36647L,36648L,36649L,36650L,
92685 36651L,36652L,36653L,36654L,36655L,36656L,36657L,36658L,36659L,36660L,
92686 36661L,36662L,36663L,36664L,36665L,36666L,36667L,36668L,36669L,36670L,
92687 36671L,36672L,36673L,36674L,36675L,36676L,36677L,36678L,36679L,36680L,
92688 36681L,36682L,36683L,36684L,36685L,36686L,36687L,36688L,36689L,36690L,
92689 36691L,36692L,36693L,36694L,36695L,36696L,36697L,36698L,36699L,36700L,
92690 36701L,36702L,36703L,36704L,36705L,36706L,36707L,36708L,36709L,36710L,
92691 36711L,36712L,36713L,36714L,36715L,36716L,36717L,36718L,36719L,36720L,
92692 36721L,36722L,36723L,36724L,36725L,36726L,36727L,36728L,36729L,36730L,
92693 36731L,36732L,36733L,36734L,36735L,36736L,36737L,36738L,36739L,36740L,
92694 36741L,36742L,36743L,36744L,36745L,36746L,36747L,36748L,36749L,36750L,
92695 36751L,36752L,36753L,36754L,36755L,36756L,36757L,36758L,36759L,36760L,
92696 36761L,36762L,36763L,36764L,36765L,36766L,36767L,36768L,36769L,36770L,
92697 36771L,36772L,36773L,36774L,36775L,36776L,36777L,36778L,36779L,36780L,
92698 36781L,36782L,36783L,36784L,36785L,36786L,36787L,36788L,36789L,36790L,
92699 36791L,36792L,36793L,36794L,36795L,36796L,36797L,36798L,36799L,36800L,
92700 36801L,36802L,36803L,36804L,36805L,36806L,36807L,36808L,36809L,36810L,
92701 36811L,36812L,36813L,36814L,36815L,36816L,36817L,36818L,36819L,36820L,
92702 36821L,36822L,36823L,36824L,36825L,36826L,36827L,36828L,36829L,36830L,
92703 36831L,36832L,36833L,36834L,36835L,36836L,36837L,36838L,36839L,36840L,
92704 36841L,36842L,36843L,36844L,36845L,36846L,36847L,36848L,36849L,36850L,
92705 36851L,36852L,36853L,36854L,36855L,36856L,36857L,36858L,36859L,36860L,
92706 36861L,36862L,36863L,36864L,36865L,36866L,36867L,36868L,36869L,36870L,
92707 36871L,36872L,36873L,36874L,36875L,36876L,36877L,36878L,36879L,36880L,
92708 36881L,36882L,36883L,36884L,36885L,36886L,36887L,36888L,36889L,36890L,
92709 36891L,36892L,36893L,36894L,36895L,36896L,36897L,36898L,36899L,36900L,
92710 36901L,36902L,36903L,36904L,36905L,36906L,36907L,36908L,36909L,36910L,
92711 36911L,36912L,36913L,36914L,36915L,36916L,36917L,36918L,36919L,36920L,
92712 36921L,36922L,36923L,36924L,36925L,36926L,36927L,36928L,36929L,36930L,
92713 36931L,36932L,36933L,36934L,36935L,36936L,36937L,36938L,36939L,36940L,
92714 36941L,36942L,36943L,36944L,36945L,36946L,36947L,36948L,36949L,36950L,
92715 36951L,36952L,36953L,36954L,36955L,36956L,36957L,36958L,36959L,36960L,
92716 36961L,36962L,36963L,36964L,36965L,36966L,36967L,36968L,36969L,36970L,
92717 36971L,36972L,36973L,36974L,36975L,36976L,36977L,36978L,36979L,36980L,
92718 36981L,36982L,36983L,36984L,36985L,36986L,36987L,36988L,36989L,36990L,
92719 36991L,36992L,36993L,36994L,36995L,36996L,36997L,36998L,36999L,37000L,
92720 37001L,37002L,37003L,37004L,37005L,37006L,37007L,37008L,37009L,37010L,
92721 37011L,37012L,37013L,37014L,37015L,37016L,37017L,37018L,37019L,37020L,
92722 37021L,37022L,37023L,37024L,37025L,37026L,37027L,37028L,37029L,37030L,
92723 37031L,37032L,37033L,37034L,37035L,37036L,37037L,37038L,37039L,37040L,
92724 37041L,37042L,37043L,37044L,37045L,37046L,37047L,37048L,37049L,37050L,
92725 37051L,37052L,37053L,37054L,37055L,37056L,37057L,37058L,37059L,37060L,
92726 37061L,37062L,37063L,37064L,37065L,37066L,37067L,37068L,37069L,37070L,
92727 37071L,37072L,37073L,37074L,37075L,37076L,37077L,37078L,37079L,37080L,
92728 37081L,37082L,37083L,37084L,37085L,37086L,37087L,37088L,37089L,37090L,
92729 37091L,37092L,37093L,37094L,37095L,37096L,37097L,37098L,37099L,37100L,
92730 37101L,37102L,37103L,37104L,37105L,37106L,37107L,37108L,37109L,37110L,
92731 37111L,37112L,37113L,37114L,37115L,37116L,37117L,37118L,37119L,37120L,
92732 37121L,37122L,37123L,37124L,37125L,37126L,37127L,37128L,37129L,37130L,
92733 37131L,37132L,37133L,37134L,37135L,37136L,37137L,37138L,37139L,37140L,
92734 37141L,37142L,37143L,37144L,37145L,37146L,37147L,37148L,37149L,37150L,
92735 37151L,37152L,37153L,37154L,37155L,37156L,37157L,37158L,37159L,37160L,
92736 37161L,37162L,37163L,37164L,37165L,37166L,37167L,37168L,37169L,37170L,
92737 37171L,37172L,37173L,37174L,37175L,37176L,37177L,37178L,37179L,37180L,
92738 37181L,37182L,37183L,37184L,37185L,37186L,37187L,37188L,37189L,37190L,
92739 37191L,37192L,37193L,37194L,37195L,37196L,37197L,37198L,37199L,37200L,
92740 37201L,37202L,37203L,37204L,37205L,37206L,37207L,37208L,37209L,37210L,
92741 37211L,37212L,37213L,37214L,37215L,37216L,37217L,37218L,37219L,37220L,
92742 37221L,37222L,37223L,37224L,37225L,37226L,37227L,37228L,37229L,37230L,
92743 37231L,37232L,37233L,37234L,37235L,37236L,37237L,37238L,37239L,37240L,
92744 37241L,37242L,37243L,37244L,37245L,37246L,37247L,37248L,37249L,37250L,
92745 37251L,37252L,37253L,37254L,37255L,37256L,37257L,37258L,37259L,37260L,
92746 37261L,37262L,37263L,37264L,37265L,37266L,37267L,37268L,37269L,37270L,
92747 37271L,37272L,37273L,37274L,37275L,37276L,37277L,37278L,37279L,37280L,
92748 37281L,37282L,37283L,37284L,37285L,37286L,37287L,37288L,37289L,37290L,
92749 37291L,37292L,37293L,37294L,37295L,37296L,37297L,37298L,37299L,37300L,
92750 37301L,37302L,37303L,37304L,37305L,37306L,37307L,37308L,37309L,37310L,
92751 37311L,37312L,37313L,37314L,37315L,37316L,37317L,37318L,37319L,37320L,
92752 37321L,37322L,37323L,37324L,37325L,37326L,37327L,37328L,37329L,37330L,
92753 37331L,37332L,37333L,37334L,37335L,37336L,37337L,37338L,37339L,37340L,
92754 37341L,37342L,37343L,37344L,37345L,37346L,37347L,37348L,37349L,37350L,
92755 37351L,37352L,37353L,37354L,37355L,37356L,37357L,37358L,37359L,37360L,
92756 37361L,37362L,37363L,37364L,37365L,37366L,37367L,37368L,37369L,37370L,
92757 37371L,37372L,37373L,37374L,37375L,37376L,37377L,37378L,37379L,37380L,
92758 37381L,37382L,37383L,37384L,37385L,37386L,37387L,37388L,37389L,37390L,
92759 37391L,37392L,37393L,37394L,37395L,37396L,37397L,37398L,37399L,37400L,
92760 37401L,37402L,37403L,37404L,37405L,37406L,37407L,37408L,37409L,37410L,
92761 37411L,37412L,37413L,37414L,37415L,37416L,37417L,37418L,37419L,37420L,
92762 37421L,37422L,37423L,37424L,37425L,37426L,37427L,37428L,37429L,37430L,
92763 37431L,37432L,37433L,37434L,37435L,37436L,37437L,37438L,37439L,37440L,
92764 37441L,37442L,37443L,37444L,37445L,37446L,37447L,37448L,37449L,37450L,
92765 37451L,37452L,37453L,37454L,37455L,37456L,37457L,37458L,37459L,37460L,
92766 37461L,37462L,37463L,37464L,37465L,37466L,37467L,37468L,37469L,37470L,
92767 37471L,37472L,37473L,37474L,37475L,37476L,37477L,37478L,37479L,37480L,
92768 37481L,37482L,37483L,37484L,37485L,37486L,37487L,37488L,37489L,37490L,
92769 37491L,37492L,37493L,37494L,37495L,37496L,37497L,37498L,37499L,37500L,
92770 37501L,37502L,37503L,37504L,37505L,37506L,37507L,37508L,37509L,37510L,
92771 37511L,37512L,37513L,37514L,37515L,37516L,37517L,37518L,37519L,37520L,
92772 37521L,37522L,37523L,37524L,37525L,37526L,37527L,37528L,37529L,37530L,
92773 37531L,37532L,37533L,37534L,37535L,37536L,37537L,37538L,37539L,37540L,
92774 37541L,37542L,37543L,37544L,37545L,37546L,37547L,37548L,37549L,37550L,
92775 37551L,37552L,37553L,37554L,37555L,37556L,37557L,37558L,37559L,37560L,
92776 37561L,37562L,37563L,37564L,37565L,37566L,37567L,37568L,37569L,37570L,
92777 37571L,37572L,37573L,37574L,37575L,37576L,37577L,37578L,37579L,37580L,
92778 37581L,37582L,37583L,37584L,37585L,37586L,37587L,37588L,37589L,37590L,
92779 37591L,37592L,37593L,37594L,37595L,37596L,37597L,37598L,37599L,37600L,
92780 37601L,37602L,37603L,37604L,37605L,37606L,37607L,37608L,37609L,37610L,
92781 37611L,37612L,37613L,37614L,37615L,37616L,37617L,37618L,37619L,37620L,
92782 37621L,37622L,37623L,37624L,37625L,37626L,37627L,37628L,37629L,37630L,
92783 37631L,37632L,37633L,37634L,37635L,37636L,37637L,37638L,37639L,37640L,
92784 37641L,37642L,37643L,37644L,37645L,37646L,37647L,37648L,37649L,37650L,
92785 37651L,37652L,37653L,37654L,37655L,37656L,37657L,37658L,37659L,37660L,
92786 37661L,37662L,37663L,37664L,37665L,37666L,37667L,37668L,37669L,37670L,
92787 37671L,37672L,37673L,37674L,37675L,37676L,37677L,37678L,37679L,37680L,
92788 37681L,37682L,37683L,37684L,37685L,37686L,37687L,37688L,37689L,37690L,
92789 37691L,37692L,37693L,37694L,37695L,37696L,37697L,37698L,37699L,37700L,
92790 37701L,37702L,37703L,37704L,37705L,37706L,37707L,37708L,37709L,37710L,
92791 37711L,37712L,37713L,37714L,37715L,37716L,37717L,37718L,37719L,37720L,
92792 37721L,37722L,37723L,37724L,37725L,37726L,37727L,37728L,37729L,37730L,
92793 37731L,37732L,37733L,37734L,37735L,37736L,37737L,37738L,37739L,37740L,
92794 37741L,37742L,37743L,37744L,37745L,37746L,37747L,37748L,37749L,37750L,
92795 37751L,37752L,37753L,37754L,37755L,37756L,37757L,37758L,37759L,37760L,
92796 37761L,37762L,37763L,37764L,37765L,37766L,37767L,37768L,37769L,37770L,
92797 37771L,37772L,37773L,37774L,37775L,37776L,37777L,37778L,37779L,37780L,
92798 37781L,37782L,37783L,37784L,37785L,37786L,37787L,37788L,37789L,37790L,
92799 37791L,37792L,37793L,37794L,37795L,37796L,37797L,37798L,37799L,37800L,
92800 37801L,37802L,37803L,37804L,37805L,37806L,37807L,37808L,37809L,37810L,
92801 37811L,37812L,37813L,37814L,37815L,37816L,37817L,37818L,37819L,37820L,
92802 37821L,37822L,37823L,37824L,37825L,37826L,37827L,37828L,37829L,37830L,
92803 37831L,37832L,37833L,37834L,37835L,37836L,37837L,37838L,37839L,37840L,
92804 37841L,37842L,37843L,37844L,37845L,37846L,37847L,37848L,37849L,37850L,
92805 37851L,37852L,37853L,37854L,37855L,37856L,37857L,37858L,37859L,37860L,
92806 37861L,37862L,37863L,37864L,37865L,37866L,37867L,37868L,37869L,37870L,
92807 37871L,37872L,37873L,37874L,37875L,37876L,37877L,37878L,37879L,37880L,
92808 37881L,37882L,37883L,37884L,37885L,37886L,37887L,37888L,37889L,37890L,
92809 37891L,37892L,37893L,37894L,37895L,37896L,37897L,37898L,37899L,37900L,
92810 37901L,37902L,37903L,37904L,37905L,37906L,37907L,37908L,37909L,37910L,
92811 37911L,37912L,37913L,37914L,37915L,37916L,37917L,37918L,37919L,37920L,
92812 37921L,37922L,37923L,37924L,37925L,37926L,37927L,37928L,37929L,37930L,
92813 37931L,37932L,37933L,37934L,37935L,37936L,37937L,37938L,37939L,37940L,
92814 37941L,37942L,37943L,37944L,37945L,37946L,37947L,37948L,37949L,37950L,
92815 37951L,37952L,37953L,37954L,37955L,37956L,37957L,37958L,37959L,37960L,
92816 37961L,37962L,37963L,37964L,37965L,37966L,37967L,37968L,37969L,37970L,
92817 37971L,37972L,37973L,37974L,37975L,37976L,37977L,37978L,37979L,37980L,
92818 37981L,37982L,37983L,37984L,37985L,37986L,37987L,37988L,37989L,37990L,
92819 37991L,37992L,37993L,37994L,37995L,37996L,37997L,37998L,37999L,38000L,
92820 38001L,38002L,38003L,38004L,38005L,38006L,38007L,38008L,38009L,38010L,
92821 38011L,38012L,38013L,38014L,38015L,38016L,38017L,38018L,38019L,38020L,
92822 38021L,38022L,38023L,38024L,38025L,38026L,38027L,38028L,38029L,38030L,
92823 38031L,38032L,38033L,38034L,38035L,38036L,38037L,38038L,38039L,38040L,
92824 38041L,38042L,38043L,38044L,38045L,38046L,38047L,38048L,38049L,38050L,
92825 38051L,38052L,38053L,38054L,38055L,38056L,38057L,38058L,38059L,38060L,
92826 38061L,38062L,38063L,38064L,38065L,38066L,38067L,38068L,38069L,38070L,
92827 38071L,38072L,38073L,38074L,38075L,38076L,38077L,38078L,38079L,38080L,
92828 38081L,38082L,38083L,38084L,38085L,38086L,38087L,38088L,38089L,38090L,
92829 38091L,38092L,38093L,38094L,38095L,38096L,38097L,38098L,38099L,38100L,
92830 38101L,38102L,38103L,38104L,38105L,38106L,38107L,38108L,38109L,38110L,
92831 38111L,38112L,38113L,38114L,38115L,38116L,38117L,38118L,38119L,38120L,
92832 38121L,38122L,38123L,38124L,38125L,38126L,38127L,38128L,38129L,38130L,
92833 38131L,38132L,38133L,38134L,38135L,38136L,38137L,38138L,38139L,38140L,
92834 38141L,38142L,38143L,38144L,38145L,38146L,38147L,38148L,38149L,38150L,
92835 38151L,38152L,38153L,38154L,38155L,38156L,38157L,38158L,38159L,38160L,
92836 38161L,38162L,38163L,38164L,38165L,38166L,38167L,38168L,38169L,38170L,
92837 38171L,38172L,38173L,38174L,38175L,38176L,38177L,38178L,38179L,38180L,
92838 38181L,38182L,38183L,38184L,38185L,38186L,38187L,38188L,38189L,38190L,
92839 38191L,38192L,38193L,38194L,38195L,38196L,38197L,38198L,38199L,38200L,
92840 38201L,38202L,38203L,38204L,38205L,38206L,38207L,38208L,38209L,38210L,
92841 38211L,38212L,38213L,38214L,38215L,38216L,38217L,38218L,38219L,38220L,
92842 38221L,38222L,38223L,38224L,38225L,38226L,38227L,38228L,38229L,38230L,
92843 38231L,38232L,38233L,38234L,38235L,38236L,38237L,38238L,38239L,38240L,
92844 38241L,38242L,38243L,38244L,38245L,38246L,38247L,38248L,38249L,38250L,
92845 38251L,38252L,38253L,38254L,38255L,38256L,38257L,38258L,38259L,38260L,
92846 38261L,38262L,38263L,38264L,38265L,38266L,38267L,38268L,38269L,38270L,
92847 38271L,38272L,38273L,38274L,38275L,38276L,38277L,38278L,38279L,38280L,
92848 38281L,38282L,38283L,38284L,38285L,38286L,38287L,38288L,38289L,38290L,
92849 38291L,38292L,38293L,38294L,38295L,38296L,38297L,38298L,38299L,38300L,
92850 38301L,38302L,38303L,38304L,38305L,38306L,38307L,38308L,38309L,38310L,
92851 38311L,38312L,38313L,38314L,38315L,38316L,38317L,38318L,38319L,38320L,
92852 38321L,38322L,38323L,38324L,38325L,38326L,38327L,38328L,38329L,38330L,
92853 38331L,38332L,38333L,38334L,38335L,38336L,38337L,38338L,38339L,38340L,
92854 38341L,38342L,38343L,38344L,38345L,38346L,38347L,38348L,38349L,38350L,
92855 38351L,38352L,38353L,38354L,38355L,38356L,38357L,38358L,38359L,38360L,
92856 38361L,38362L,38363L,38364L,38365L,38366L,38367L,38368L,38369L,38370L,
92857 38371L,38372L,38373L,38374L,38375L,38376L,38377L,38378L,38379L,38380L,
92858 38381L,38382L,38383L,38384L,38385L,38386L,38387L,38388L,38389L,38390L,
92859 38391L,38392L,38393L,38394L,38395L,38396L,38397L,38398L,38399L,38400L,
92860 38401L,38402L,38403L,38404L,38405L,38406L,38407L,38408L,38409L,38410L,
92861 38411L,38412L,38413L,38414L,38415L,38416L,38417L,38418L,38419L,38420L,
92862 38421L,38422L,38423L,38424L,38425L,38426L,38427L,38428L,38429L,38430L,
92863 38431L,38432L,38433L,38434L,38435L,38436L,38437L,38438L,38439L,38440L,
92864 38441L,38442L,38443L,38444L,38445L,38446L,38447L,38448L,38449L,38450L,
92865 38451L,38452L,38453L,38454L,38455L,38456L,38457L,38458L,38459L,38460L,
92866 38461L,38462L,38463L,38464L,38465L,38466L,38467L,38468L,38469L,38470L,
92867 38471L,38472L,38473L,38474L,38475L,38476L,38477L,38478L,38479L,38480L,
92868 38481L,38482L,38483L,38484L,38485L,38486L,38487L,38488L,38489L,38490L,
92869 38491L,38492L,38493L,38494L,38495L,38496L,38497L,38498L,38499L,38500L,
92870 38501L,38502L,38503L,38504L,38505L,38506L,38507L,38508L,38509L,38510L,
92871 38511L,38512L,38513L,38514L,38515L,38516L,38517L,38518L,38519L,38520L,
92872 38521L,38522L,38523L,38524L,38525L,38526L,38527L,38528L,38529L,38530L,
92873 38531L,38532L,38533L,38534L,38535L,38536L,38537L,38538L,38539L,38540L,
92874 38541L,38542L,38543L,38544L,38545L,38546L,38547L,38548L,38549L,38550L,
92875 38551L,38552L,38553L,38554L,38555L,38556L,38557L,38558L,38559L,38560L,
92876 38561L,38562L,38563L,38564L,38565L,38566L,38567L,38568L,38569L,38570L,
92877 38571L,38572L,38573L,38574L,38575L,38576L,38577L,38578L,38579L,38580L,
92878 38581L,38582L,38583L,38584L,38585L,38586L,38587L,38588L,38589L,38590L,
92879 38591L,38592L,38593L,38594L,38595L,38596L,38597L,38598L,38599L,38600L,
92880 38601L,38602L,38603L,38604L,38605L,38606L,38607L,38608L,38609L,38610L,
92881 38611L,38612L,38613L,38614L,38615L,38616L,38617L,38618L,38619L,38620L,
92882 38621L,38622L,38623L,38624L,38625L,38626L,38627L,38628L,38629L,38630L,
92883 38631L,38632L,38633L,38634L,38635L,38636L,38637L,38638L,38639L,38640L,
92884 38641L,38642L,38643L,38644L,38645L,38646L,38647L,38648L,38649L,38650L,
92885 38651L,38652L,38653L,38654L,38655L,38656L,38657L,38658L,38659L,38660L,
92886 38661L,38662L,38663L,38664L,38665L,38666L,38667L,38668L,38669L,38670L,
92887 38671L,38672L,38673L,38674L,38675L,38676L,38677L,38678L,38679L,38680L,
92888 38681L,38682L,38683L,38684L,38685L,38686L,38687L,38688L,38689L,38690L,
92889 38691L,38692L,38693L,38694L,38695L,38696L,38697L,38698L,38699L,38700L,
92890 38701L,38702L,38703L,38704L,38705L,38706L,38707L,38708L,38709L,38710L,
92891 38711L,38712L,38713L,38714L,38715L,38716L,38717L,38718L,38719L,38720L,
92892 38721L,38722L,38723L,38724L,38725L,38726L,38727L,38728L,38729L,38730L,
92893 38731L,38732L,38733L,38734L,38735L,38736L,38737L,38738L,38739L,38740L,
92894 38741L,38742L,38743L,38744L,38745L,38746L,38747L,38748L,38749L,38750L,
92895 38751L,38752L,38753L,38754L,38755L,38756L,38757L,38758L,38759L,38760L,
92896 38761L,38762L,38763L,38764L,38765L,38766L,38767L,38768L,38769L,38770L,
92897 38771L,38772L,38773L,38774L,38775L,38776L,38777L,38778L,38779L,38780L,
92898 38781L,38782L,38783L,38784L,38785L,38786L,38787L,38788L,38789L,38790L,
92899 38791L,38792L,38793L,38794L,38795L,38796L,38797L,38798L,38799L,38800L,
92900 38801L,38802L,38803L,38804L,38805L,38806L,38807L,38808L,38809L,38810L,
92901 38811L,38812L,38813L,38814L,38815L,38816L,38817L,38818L,38819L,38820L,
92902 38821L,38822L,38823L,38824L,38825L,38826L,38827L,38828L,38829L,38830L,
92903 38831L,38832L,38833L,38834L,38835L,38836L,38837L,38838L,38839L,38840L,
92904 38841L,38842L,38843L,38844L,38845L,38846L,38847L,38848L,38849L,38850L,
92905 38851L,38852L,38853L,38854L,38855L,38856L,38857L,38858L,38859L,38860L,
92906 38861L,38862L,38863L,38864L,38865L,38866L,38867L,38868L,38869L,38870L,
92907 38871L,38872L,38873L,38874L,38875L,38876L,38877L,38878L,38879L,38880L,
92908 38881L,38882L,38883L,38884L,38885L,38886L,38887L,38888L,38889L,38890L,
92909 38891L,38892L,38893L,38894L,38895L,38896L,38897L,38898L,38899L,38900L,
92910 38901L,38902L,38903L,38904L,38905L,38906L,38907L,38908L,38909L,38910L,
92911 38911L,38912L,38913L,38914L,38915L,38916L,38917L,38918L,38919L,38920L,
92912 38921L,38922L,38923L,38924L,38925L,38926L,38927L,38928L,38929L,38930L,
92913 38931L,38932L,38933L,38934L,38935L,38936L,38937L,38938L,38939L,38940L,
92914 38941L,38942L,38943L,38944L,38945L,38946L,38947L,38948L,38949L,38950L,
92915 38951L,38952L,38953L,38954L,38955L,38956L,38957L,38958L,38959L,38960L,
92916 38961L,38962L,38963L,38964L,38965L,38966L,38967L,38968L,38969L,38970L,
92917 38971L,38972L,38973L,38974L,38975L,38976L,38977L,38978L,38979L,38980L,
92918 38981L,38982L,38983L,38984L,38985L,38986L,38987L,38988L,38989L,38990L,
92919 38991L,38992L,38993L,38994L,38995L,38996L,38997L,38998L,38999L,39000L,
92920 39001L,39002L,39003L,39004L,39005L,39006L,39007L,39008L,39009L,39010L,
92921 39011L,39012L,39013L,39014L,39015L,39016L,39017L,39018L,39019L,39020L,
92922 39021L,39022L,39023L,39024L,39025L,39026L,39027L,39028L,39029L,39030L,
92923 39031L,39032L,39033L,39034L,39035L,39036L,39037L,39038L,39039L,39040L,
92924 39041L,39042L,39043L,39044L,39045L,39046L,39047L,39048L,39049L,39050L,
92925 39051L,39052L,39053L,39054L,39055L,39056L,39057L,39058L,39059L,39060L,
92926 39061L,39062L,39063L,39064L,39065L,39066L,39067L,39068L,39069L,39070L,
92927 39071L,39072L,39073L,39074L,39075L,39076L,39077L,39078L,39079L,39080L,
92928 39081L,39082L,39083L,39084L,39085L,39086L,39087L,39088L,39089L,39090L,
92929 39091L,39092L,39093L,39094L,39095L,39096L,39097L,39098L,39099L,39100L,
92930 39101L,39102L,39103L,39104L,39105L,39106L,39107L,39108L,39109L,39110L,
92931 39111L,39112L,39113L,39114L,39115L,39116L,39117L,39118L,39119L,39120L,
92932 39121L,39122L,39123L,39124L,39125L,39126L,39127L,39128L,39129L,39130L,
92933 39131L,39132L,39133L,39134L,39135L,39136L,39137L,39138L,39139L,39140L,
92934 39141L,39142L,39143L,39144L,39145L,39146L,39147L,39148L,39149L,39150L,
92935 39151L,39152L,39153L,39154L,39155L,39156L,39157L,39158L,39159L,39160L,
92936 39161L,39162L,39163L,39164L,39165L,39166L,39167L,39168L,39169L,39170L,
92937 39171L,39172L,39173L,39174L,39175L,39176L,39177L,39178L,39179L,39180L,
92938 39181L,39182L,39183L,39184L,39185L,39186L,39187L,39188L,39189L,39190L,
92939 39191L,39192L,39193L,39194L,39195L,39196L,39197L,39198L,39199L,39200L,
92940 39201L,39202L,39203L,39204L,39205L,39206L,39207L,39208L,39209L,39210L,
92941 39211L,39212L,39213L,39214L,39215L,39216L,39217L,39218L,39219L,39220L,
92942 39221L,39222L,39223L,39224L,39225L,39226L,39227L,39228L,39229L,39230L,
92943 39231L,39232L,39233L,39234L,39235L,39236L,39237L,39238L,39239L,39240L,
92944 39241L,39242L,39243L,39244L,39245L,39246L,39247L,39248L,39249L,39250L,
92945 39251L,39252L,39253L,39254L,39255L,39256L,39257L,39258L,39259L,39260L,
92946 39261L,39262L,39263L,39264L,39265L,39266L,39267L,39268L,39269L,39270L,
92947 39271L,39272L,39273L,39274L,39275L,39276L,39277L,39278L,39279L,39280L,
92948 39281L,39282L,39283L,39284L,39285L,39286L,39287L,39288L,39289L,39290L,
92949 39291L,39292L,39293L,39294L,39295L,39296L,39297L,39298L,39299L,39300L,
92950 39301L,39302L,39303L,39304L,39305L,39306L,39307L,39308L,39309L,39310L,
92951 39311L,39312L,39313L,39314L,39315L,39316L,39317L,39318L,39319L,39320L,
92952 39321L,39322L,39323L,39324L,39325L,39326L,39327L,39328L,39329L,39330L,
92953 39331L,39332L,39333L,39334L,39335L,39336L,39337L,39338L,39339L,39340L,
92954 39341L,39342L,39343L,39344L,39345L,39346L,39347L,39348L,39349L,39350L,
92955 39351L,39352L,39353L,39354L,39355L,39356L,39357L,39358L,39359L,39360L,
92956 39361L,39362L,39363L,39364L,39365L,39366L,39367L,39368L,39369L,39370L,
92957 39371L,39372L,39373L,39374L,39375L,39376L,39377L,39378L,39379L,39380L,
92958 39381L,39382L,39383L,39384L,39385L,39386L,39387L,39388L,39389L,39390L,
92959 39391L,39392L,39393L,39394L,39395L,39396L,39397L,39398L,39399L,39400L,
92960 39401L,39402L,39403L,39404L,39405L,39406L,39407L,39408L,39409L,39410L,
92961 39411L,39412L,39413L,39414L,39415L,39416L,39417L,39418L,39419L,39420L,
92962 39421L,39422L,39423L,39424L,39425L,39426L,39427L,39428L,39429L,39430L,
92963 39431L,39432L,39433L,39434L,39435L,39436L,39437L,39438L,39439L,39440L,
92964 39441L,39442L,39443L,39444L,39445L,39446L,39447L,39448L,39449L,39450L,
92965 39451L,39452L,39453L,39454L,39455L,39456L,39457L,39458L,39459L,39460L,
92966 39461L,39462L,39463L,39464L,39465L,39466L,39467L,39468L,39469L,39470L,
92967 39471L,39472L,39473L,39474L,39475L,39476L,39477L,39478L,39479L,39480L,
92968 39481L,39482L,39483L,39484L,39485L,39486L,39487L,39488L,39489L,39490L,
92969 39491L,39492L,39493L,39494L,39495L,39496L,39497L,39498L,39499L,39500L,
92970 39501L,39502L,39503L,39504L,39505L,39506L,39507L,39508L,39509L,39510L,
92971 39511L,39512L,39513L,39514L,39515L,39516L,39517L,39518L,39519L,39520L,
92972 39521L,39522L,39523L,39524L,39525L,39526L,39527L,39528L,39529L,39530L,
92973 39531L,39532L,39533L,39534L,39535L,39536L,39537L,39538L,39539L,39540L,
92974 39541L,39542L,39543L,39544L,39545L,39546L,39547L,39548L,39549L,39550L,
92975 39551L,39552L,39553L,39554L,39555L,39556L,39557L,39558L,39559L,39560L,
92976 39561L,39562L,39563L,39564L,39565L,39566L,39567L,39568L,39569L,39570L,
92977 39571L,39572L,39573L,39574L,39575L,39576L,39577L,39578L,39579L,39580L,
92978 39581L,39582L,39583L,39584L,39585L,39586L,39587L,39588L,39589L,39590L,
92979 39591L,39592L,39593L,39594L,39595L,39596L,39597L,39598L,39599L,39600L,
92980 39601L,39602L,39603L,39604L,39605L,39606L,39607L,39608L,39609L,39610L,
92981 39611L,39612L,39613L,39614L,39615L,39616L,39617L,39618L,39619L,39620L,
92982 39621L,39622L,39623L,39624L,39625L,39626L,39627L,39628L,39629L,39630L,
92983 39631L,39632L,39633L,39634L,39635L,39636L,39637L,39638L,39639L,39640L,
92984 39641L,39642L,39643L,39644L,39645L,39646L,39647L,39648L,39649L,39650L,
92985 39651L,39652L,39653L,39654L,39655L,39656L,39657L,39658L,39659L,39660L,
92986 39661L,39662L,39663L,39664L,39665L,39666L,39667L,39668L,39669L,39670L,
92987 39671L,39672L,39673L,39674L,39675L,39676L,39677L,39678L,39679L,39680L,
92988 39681L,39682L,39683L,39684L,39685L,39686L,39687L,39688L,39689L,39690L,
92989 39691L,39692L,39693L,39694L,39695L,39696L,39697L,39698L,39699L,39700L,
92990 39701L,39702L,39703L,39704L,39705L,39706L,39707L,39708L,39709L,39710L,
92991 39711L,39712L,39713L,39714L,39715L,39716L,39717L,39718L,39719L,39720L,
92992 39721L,39722L,39723L,39724L,39725L,39726L,39727L,39728L,39729L,39730L,
92993 39731L,39732L,39733L,39734L,39735L,39736L,39737L,39738L,39739L,39740L,
92994 39741L,39742L,39743L,39744L,39745L,39746L,39747L,39748L,39749L,39750L,
92995 39751L,39752L,39753L,39754L,39755L,39756L,39757L,39758L,39759L,39760L,
92996 39761L,39762L,39763L,39764L,39765L,39766L,39767L,39768L,39769L,39770L,
92997 39771L,39772L,39773L,39774L,39775L,39776L,39777L,39778L,39779L,39780L,
92998 39781L,39782L,39783L,39784L,39785L,39786L,39787L,39788L,39789L,39790L,
92999 39791L,39792L,39793L,39794L,39795L,39796L,39797L,39798L,39799L,39800L,
93000 39801L,39802L,39803L,39804L,39805L,39806L,39807L,39808L,39809L,39810L,
93001 39811L,39812L,39813L,39814L,39815L,39816L,39817L,39818L,39819L,39820L,
93002 39821L,39822L,39823L,39824L,39825L,39826L,39827L,39828L,39829L,39830L,
93003 39831L,39832L,39833L,39834L,39835L,39836L,39837L,39838L,39839L,39840L,
93004 39841L,39842L,39843L,39844L,39845L,39846L,39847L,39848L,39849L,39850L,
93005 39851L,39852L,39853L,39854L,39855L,39856L,39857L,39858L,39859L,39860L,
93006 39861L,39862L,39863L,39864L,39865L,39866L,39867L,39868L,39869L,39870L,
93007 39871L,39872L,39873L,39874L,39875L,39876L,39877L,39878L,39879L,39880L,
93008 39881L,39882L,39883L,39884L,39885L,39886L,39887L,39888L,39889L,39890L,
93009 39891L,39892L,39893L,39894L,39895L,39896L,39897L,39898L,39899L,39900L,
93010 39901L,39902L,39903L,39904L,39905L,39906L,39907L,39908L,39909L,39910L,
93011 39911L,39912L,39913L,39914L,39915L,39916L,39917L,39918L,39919L,39920L,
93012 39921L,39922L,39923L,39924L,39925L,39926L,39927L,39928L,39929L,39930L,
93013 39931L,39932L,39933L,39934L,39935L,39936L,39937L,39938L,39939L,39940L,
93014 39941L,39942L,39943L,39944L,39945L,39946L,39947L,39948L,39949L,39950L,
93015 39951L,39952L,39953L,39954L,39955L,39956L,39957L,39958L,39959L,39960L,
93016 39961L,39962L,39963L,39964L,39965L,39966L,39967L,39968L,39969L,39970L,
93017 39971L,39972L,39973L,39974L,39975L,39976L,39977L,39978L,39979L,39980L,
93018 39981L,39982L,39983L,39984L,39985L,39986L,39987L,39988L,39989L,39990L,
93019 39991L,39992L,39993L,39994L,39995L,39996L,39997L,39998L,39999L,40000L,
93020 40001L,40002L,40003L,40004L,40005L,40006L,40007L,40008L,40009L,40010L,
93021 40011L,40012L,40013L,40014L,40015L,40016L,40017L,40018L,40019L,40020L,
93022 40021L,40022L,40023L,40024L,40025L,40026L,40027L,40028L,40029L,40030L,
93023 40031L,40032L,40033L,40034L,40035L,40036L,40037L,40038L,40039L,40040L,
93024 40041L,40042L,40043L,40044L,40045L,40046L,40047L,40048L,40049L,40050L,
93025 40051L,40052L,40053L,40054L,40055L,40056L,40057L,40058L,40059L,40060L,
93026 40061L,40062L,40063L,40064L,40065L,40066L,40067L,40068L,40069L,40070L,
93027 40071L,40072L,40073L,40074L,40075L,40076L,40077L,40078L,40079L,40080L,
93028 40081L,40082L,40083L,40084L,40085L,40086L,40087L,40088L,40089L,40090L,
93029 40091L,40092L,40093L,40094L,40095L,40096L,40097L,40098L,40099L,40100L,
93030 40101L,40102L,40103L,40104L,40105L,40106L,40107L,40108L,40109L,40110L,
93031 40111L,40112L,40113L,40114L,40115L,40116L,40117L,40118L,40119L,40120L,
93032 40121L,40122L,40123L,40124L,40125L,40126L,40127L,40128L,40129L,40130L,
93033 40131L,40132L,40133L,40134L,40135L,40136L,40137L,40138L,40139L,40140L,
93034 40141L,40142L,40143L,40144L,40145L,40146L,40147L,40148L,40149L,40150L,
93035 40151L,40152L,40153L,40154L,40155L,40156L,40157L,40158L,40159L,40160L,
93036 40161L,40162L,40163L,40164L,40165L,40166L,40167L,40168L,40169L,40170L,
93037 40171L,40172L,40173L,40174L,40175L,40176L,40177L,40178L,40179L,40180L,
93038 40181L,40182L,40183L,40184L,40185L,40186L,40187L,40188L,40189L,40190L,
93039 40191L,40192L,40193L,40194L,40195L,40196L,40197L,40198L,40199L,40200L,
93040 40201L,40202L,40203L,40204L,40205L,40206L,40207L,40208L,40209L,40210L,
93041 40211L,40212L,40213L,40214L,40215L,40216L,40217L,40218L,40219L,40220L,
93042 40221L,40222L,40223L,40224L,40225L,40226L,40227L,40228L,40229L,40230L,
93043 40231L,40232L,40233L,40234L,40235L,40236L,40237L,40238L,40239L,40240L,
93044 40241L,40242L,40243L,40244L,40245L,40246L,40247L,40248L,40249L,40250L,
93045 40251L,40252L,40253L,40254L,40255L,40256L,40257L,40258L,40259L,40260L,
93046 40261L,40262L,40263L,40264L,40265L,40266L,40267L,40268L,40269L,40270L,
93047 40271L,40272L,40273L,40274L,40275L,40276L,40277L,40278L,40279L,40280L,
93048 40281L,40282L,40283L,40284L,40285L,40286L,40287L,40288L,40289L,40290L,
93049 40291L,40292L,40293L,40294L,40295L,40296L,40297L,40298L,40299L,40300L,
93050 40301L,40302L,40303L,40304L,40305L,40306L,40307L,40308L,40309L,40310L,
93051 40311L,40312L,40313L,40314L,40315L,40316L,40317L,40318L,40319L,40320L,
93052 40321L,40322L,40323L,40324L,40325L,40326L,40327L,40328L,40329L,40330L,
93053 40331L,40332L,40333L,40334L,40335L,40336L,40337L,40338L,40339L,40340L,
93054 40341L,40342L,40343L,40344L,40345L,40346L,40347L,40348L,40349L,40350L,
93055 40351L,40352L,40353L,40354L,40355L,40356L,40357L,40358L,40359L,40360L,
93056 40361L,40362L,40363L,40364L,40365L,40366L,40367L,40368L,40369L,40370L,
93057 40371L,40372L,40373L,40374L,40375L,40376L,40377L,40378L,40379L,40380L,
93058 40381L,40382L,40383L,40384L,40385L,40386L,40387L,40388L,40389L,40390L,
93059 40391L,40392L,40393L,40394L,40395L,40396L,40397L,40398L,40399L,40400L,
93060 40401L,40402L,40403L,40404L,40405L,40406L,40407L,40408L,40409L,40410L,
93061 40411L,40412L,40413L,40414L,40415L,40416L,40417L,40418L,40419L,40420L,
93062 40421L,40422L,40423L,40424L,40425L,40426L,40427L,40428L,40429L,40430L,
93063 40431L,40432L,40433L,40434L,40435L,40436L,40437L,40438L,40439L,40440L,
93064 40441L,40442L,40443L,40444L,40445L,40446L,40447L,40448L,40449L,40450L,
93065 40451L,40452L,40453L,40454L,40455L,40456L,40457L,40458L,40459L,40460L,
93066 40461L,40462L,40463L,40464L,40465L,40466L,40467L,40468L,40469L,40470L,
93067 40471L,40472L,40473L,40474L,40475L,40476L,40477L,40478L,40479L,40480L,
93068 40481L,40482L,40483L,40484L,40485L,40486L,40487L,40488L,40489L,40490L,
93069 40491L,40492L,40493L,40494L,40495L,40496L,40497L,40498L,40499L,40500L,
93070 40501L,40502L,40503L,40504L,40505L,40506L,40507L,40508L,40509L,40510L,
93071 40511L,40512L,40513L,40514L,40515L,40516L,40517L,40518L,40519L,40520L,
93072 40521L,40522L,40523L,40524L,40525L,40526L,40527L,40528L,40529L,40530L,
93073 40531L,40532L,40533L,40534L,40535L,40536L,40537L,40538L,40539L,40540L,
93074 40541L,40542L,40543L,40544L,40545L,40546L,40547L,40548L,40549L,40550L,
93075 40551L,40552L,40553L,40554L,40555L,40556L,40557L,40558L,40559L,40560L,
93076 40561L,40562L,40563L,40564L,40565L,40566L,40567L,40568L,40569L,40570L,
93077 40571L,40572L,40573L,40574L,40575L,40576L,40577L,40578L,40579L,40580L,
93078 40581L,40582L,40583L,40584L,40585L,40586L,40587L,40588L,40589L,40590L,
93079 40591L,40592L,40593L,40594L,40595L,40596L,40597L,40598L,40599L,40600L,
93080 40601L,40602L,40603L,40604L,40605L,40606L,40607L,40608L,40609L,40610L,
93081 40611L,40612L,40613L,40614L,40615L,40616L,40617L,40618L,40619L,40620L,
93082 40621L,40622L,40623L,40624L,40625L,40626L,40627L,40628L,40629L,40630L,
93083 40631L,40632L,40633L,40634L,40635L,40636L,40637L,40638L,40639L,40640L,
93084 40641L,40642L,40643L,40644L,40645L,40646L,40647L,40648L,40649L,40650L,
93085 40651L,40652L,40653L,40654L,40655L,40656L,40657L,40658L,40659L,40660L,
93086 40661L,40662L,40663L,40664L,40665L,40666L,40667L,40668L,40669L,40670L,
93087 40671L,40672L,40673L,40674L,40675L,40676L,40677L,40678L,40679L,40680L,
93088 40681L,40682L,40683L,40684L,40685L,40686L,40687L,40688L,40689L,40690L,
93089 40691L,40692L,40693L,40694L,40695L,40696L,40697L,40698L,40699L,40700L,
93090 40701L,40702L,40703L,40704L,40705L,40706L,40707L,40708L,40709L,40710L,
93091 40711L,40712L,40713L,40714L,40715L,40716L,40717L,40718L,40719L,40720L,
93092 40721L,40722L,40723L,40724L,40725L,40726L,40727L,40728L,40729L,40730L,
93093 40731L,40732L,40733L,40734L,40735L,40736L,40737L,40738L,40739L,40740L,
93094 40741L,40742L,40743L,40744L,40745L,40746L,40747L,40748L,40749L,40750L,
93095 40751L,40752L,40753L,40754L,40755L,40756L,40757L,40758L,40759L,40760L,
93096 40761L,40762L,40763L,40764L,40765L,40766L,40767L,40768L,40769L,40770L,
93097 40771L,40772L,40773L,40774L,40775L,40776L,40777L,40778L,40779L,40780L,
93098 40781L,40782L,40783L,40784L,40785L,40786L,40787L,40788L,40789L,40790L,
93099 40791L,40792L,40793L,40794L,40795L,40796L,40797L,40798L,40799L,40800L,
93100 40801L,40802L,40803L,40804L,40805L,40806L,40807L,40808L,40809L,40810L,
93101 40811L,40812L,40813L,40814L,40815L,40816L,40817L,40818L,40819L,40820L,
93102 40821L,40822L,40823L,40824L,40825L,40826L,40827L,40828L,40829L,40830L,
93103 40831L,40832L,40833L,40834L,40835L,40836L,40837L,40838L,40839L,40840L,
93104 40841L,40842L,40843L,40844L,40845L,40846L,40847L,40848L,40849L,40850L,
93105 40851L,40852L,40853L,40854L,40855L,40856L,40857L,40858L,40859L,40860L,
93106 40861L,40862L,40863L,40864L,40865L,40866L,40867L,40868L,40869L,40870L,
93107 40871L,40872L,40873L,40874L,40875L,40876L,40877L,40878L,40879L,40880L,
93108 40881L,40882L,40883L,40884L,40885L,40886L,40887L,40888L,40889L,40890L,
93109 40891L,40892L,40893L,40894L,40895L,40896L,40897L,40898L,40899L,40900L,
93110 40901L,40902L,40903L,40904L,40905L,40906L,40907L,40908L,40909L,40910L,
93111 40911L,40912L,40913L,40914L,40915L,40916L,40917L,40918L,40919L,40920L,
93112 40921L,40922L,40923L,40924L,40925L,40926L,40927L,40928L,40929L,40930L,
93113 40931L,40932L,40933L,40934L,40935L,40936L,40937L,40938L,40939L,40940L,
93114 40941L,40942L,40943L,40944L,40945L,40946L,40947L,40948L,40949L,40950L,
93115 40951L,40952L,40953L,40954L,40955L,40956L,40957L,40958L,40959L,40960L,
93116 40961L,40962L,40963L,40964L,40965L,40966L,40967L,40968L,40969L,40970L,
93117 40971L,40972L,40973L,40974L,40975L,40976L,40977L,40978L,40979L,40980L,
93118 40981L,40982L,40983L,40984L,40985L,40986L,40987L,40988L,40989L,40990L,
93119 40991L,40992L,40993L,40994L,40995L,40996L,40997L,40998L,40999L,41000L,
93120 41001L,41002L,41003L,41004L,41005L,41006L,41007L,41008L,41009L,41010L,
93121 41011L,41012L,41013L,41014L,41015L,41016L,41017L,41018L,41019L,41020L,
93122 41021L,41022L,41023L,41024L,41025L,41026L,41027L,41028L,41029L,41030L,
93123 41031L,41032L,41033L,41034L,41035L,41036L,41037L,41038L,41039L,41040L,
93124 41041L,41042L,41043L,41044L,41045L,41046L,41047L,41048L,41049L,41050L,
93125 41051L,41052L,41053L,41054L,41055L,41056L,41057L,41058L,41059L,41060L,
93126 41061L,41062L,41063L,41064L,41065L,41066L,41067L,41068L,41069L,41070L,
93127 41071L,41072L,41073L,41074L,41075L,41076L,41077L,41078L,41079L,41080L,
93128 41081L,41082L,41083L,41084L,41085L,41086L,41087L,41088L,41089L,41090L,
93129 41091L,41092L,41093L,41094L,41095L,41096L,41097L,41098L,41099L,41100L,
93130 41101L,41102L,41103L,41104L,41105L,41106L,41107L,41108L,41109L,41110L,
93131 41111L,41112L,41113L,41114L,41115L,41116L,41117L,41118L,41119L,41120L,
93132 41121L,41122L,41123L,41124L,41125L,41126L,41127L,41128L,41129L,41130L,
93133 41131L,41132L,41133L,41134L,41135L,41136L,41137L,41138L,41139L,41140L,
93134 41141L,41142L,41143L,41144L,41145L,41146L,41147L,41148L,41149L,41150L,
93135 41151L,41152L,41153L,41154L,41155L,41156L,41157L,41158L,41159L,41160L,
93136 41161L,41162L,41163L,41164L,41165L,41166L,41167L,41168L,41169L,41170L,
93137 41171L,41172L,41173L,41174L,41175L,41176L,41177L,41178L,41179L,41180L,
93138 41181L,41182L,41183L,41184L,41185L,41186L,41187L,41188L,41189L,41190L,
93139 41191L,41192L,41193L,41194L,41195L,41196L,41197L,41198L,41199L,41200L,
93140 41201L,41202L,41203L,41204L,41205L,41206L,41207L,41208L,41209L,41210L,
93141 41211L,41212L,41213L,41214L,41215L,41216L,41217L,41218L,41219L,41220L,
93142 41221L,41222L,41223L,41224L,41225L,41226L,41227L,41228L,41229L,41230L,
93143 41231L,41232L,41233L,41234L,41235L,41236L,41237L,41238L,41239L,41240L,
93144 41241L,41242L,41243L,41244L,41245L,41246L,41247L,41248L,41249L,41250L,
93145 41251L,41252L,41253L,41254L,41255L,41256L,41257L,41258L,41259L,41260L,
93146 41261L,41262L,41263L,41264L,41265L,41266L,41267L,41268L,41269L,41270L,
93147 41271L,41272L,41273L,41274L,41275L,41276L,41277L,41278L,41279L,41280L,
93148 41281L,41282L,41283L,41284L,41285L,41286L,41287L,41288L,41289L,41290L,
93149 41291L,41292L,41293L,41294L,41295L,41296L,41297L,41298L,41299L,41300L,
93150 41301L,41302L,41303L,41304L,41305L,41306L,41307L,41308L,41309L,41310L,
93151 41311L,41312L,41313L,41314L,41315L,41316L,41317L,41318L,41319L,41320L,
93152 41321L,41322L,41323L,41324L,41325L,41326L,41327L,41328L,41329L,41330L,
93153 41331L,41332L,41333L,41334L,41335L,41336L,41337L,41338L,41339L,41340L,
93154 41341L,41342L,41343L,41344L,41345L,41346L,41347L,41348L,41349L,41350L,
93155 41351L,41352L,41353L,41354L,41355L,41356L,41357L,41358L,41359L,41360L,
93156 41361L,41362L,41363L,41364L,41365L,41366L,41367L,41368L,41369L,41370L,
93157 41371L,41372L,41373L,41374L,41375L,41376L,41377L,41378L,41379L,41380L,
93158 41381L,41382L,41383L,41384L,41385L,41386L,41387L,41388L,41389L,41390L,
93159 41391L,41392L,41393L,41394L,41395L,41396L,41397L,41398L,41399L,41400L,
93160 41401L,41402L,41403L,41404L,41405L,41406L,41407L,41408L,41409L,41410L,
93161 41411L,41412L,41413L,41414L,41415L,41416L,41417L,41418L,41419L,41420L,
93162 41421L,41422L,41423L,41424L,41425L,41426L,41427L,41428L,41429L,41430L,
93163 41431L,41432L,41433L,41434L,41435L,41436L,41437L,41438L,41439L,41440L,
93164 41441L,41442L,41443L,41444L,41445L,41446L,41447L,41448L,41449L,41450L,
93165 41451L,41452L,41453L,41454L,41455L,41456L,41457L,41458L,41459L,41460L,
93166 41461L,41462L,41463L,41464L,41465L,41466L,41467L,41468L,41469L,41470L,
93167 41471L,41472L,41473L,41474L,41475L,41476L,41477L,41478L,41479L,41480L,
93168 41481L,41482L,41483L,41484L,41485L,41486L,41487L,41488L,41489L,41490L,
93169 41491L,41492L,41493L,41494L,41495L,41496L,41497L,41498L,41499L,41500L,
93170 41501L,41502L,41503L,41504L,41505L,41506L,41507L,41508L,41509L,41510L,
93171 41511L,41512L,41513L,41514L,41515L,41516L,41517L,41518L,41519L,41520L,
93172 41521L,41522L,41523L,41524L,41525L,41526L,41527L,41528L,41529L,41530L,
93173 41531L,41532L,41533L,41534L,41535L,41536L,41537L,41538L,41539L,41540L,
93174 41541L,41542L,41543L,41544L,41545L,41546L,41547L,41548L,41549L,41550L,
93175 41551L,41552L,41553L,41554L,41555L,41556L,41557L,41558L,41559L,41560L,
93176 41561L,41562L,41563L,41564L,41565L,41566L,41567L,41568L,41569L,41570L,
93177 41571L,41572L,41573L,41574L,41575L,41576L,41577L,41578L,41579L,41580L,
93178 41581L,41582L,41583L,41584L,41585L,41586L,41587L,41588L,41589L,41590L,
93179 41591L,41592L,41593L,41594L,41595L,41596L,41597L,41598L,41599L,41600L,
93180 41601L,41602L,41603L,41604L,41605L,41606L,41607L,41608L,41609L,41610L,
93181 41611L,41612L,41613L,41614L,41615L,41616L,41617L,41618L,41619L,41620L,
93182 41621L,41622L,41623L,41624L,41625L,41626L,41627L,41628L,41629L,41630L,
93183 41631L,41632L,41633L,41634L,41635L,41636L,41637L,41638L,41639L,41640L,
93184 41641L,41642L,41643L,41644L,41645L,41646L,41647L,41648L,41649L,41650L,
93185 41651L,41652L,41653L,41654L,41655L,41656L,41657L,41658L,41659L,41660L,
93186 41661L,41662L,41663L,41664L,41665L,41666L,41667L,41668L,41669L,41670L,
93187 41671L,41672L,41673L,41674L,41675L,41676L,41677L,41678L,41679L,41680L,
93188 41681L,41682L,41683L,41684L,41685L,41686L,41687L,41688L,41689L,41690L,
93189 41691L,41692L,41693L,41694L,41695L,41696L,41697L,41698L,41699L,41700L,
93190 41701L,41702L,41703L,41704L,41705L,41706L,41707L,41708L,41709L,41710L,
93191 41711L,41712L,41713L,41714L,41715L,41716L,41717L,41718L,41719L,41720L,
93192 41721L,41722L,41723L,41724L,41725L,41726L,41727L,41728L,41729L,41730L,
93193 41731L,41732L,41733L,41734L,41735L,41736L,41737L,41738L,41739L,41740L,
93194 41741L,41742L,41743L,41744L,41745L,41746L,41747L,41748L,41749L,41750L,
93195 41751L,41752L,41753L,41754L,41755L,41756L,41757L,41758L,41759L,41760L,
93196 41761L,41762L,41763L,41764L,41765L,41766L,41767L,41768L,41769L,41770L,
93197 41771L,41772L,41773L,41774L,41775L,41776L,41777L,41778L,41779L,41780L,
93198 41781L,41782L,41783L,41784L,41785L,41786L,41787L,41788L,41789L,41790L,
93199 41791L,41792L,41793L,41794L,41795L,41796L,41797L,41798L,41799L,41800L,
93200 41801L,41802L,41803L,41804L,41805L,41806L,41807L,41808L,41809L,41810L,
93201 41811L,41812L,41813L,41814L,41815L,41816L,41817L,41818L,41819L,41820L,
93202 41821L,41822L,41823L,41824L,41825L,41826L,41827L,41828L,41829L,41830L,
93203 41831L,41832L,41833L,41834L,41835L,41836L,41837L,41838L,41839L,41840L,
93204 41841L,41842L,41843L,41844L,41845L,41846L,41847L,41848L,41849L,41850L,
93205 41851L,41852L,41853L,41854L,41855L,41856L,41857L,41858L,41859L,41860L,
93206 41861L,41862L,41863L,41864L,41865L,41866L,41867L,41868L,41869L,41870L,
93207 41871L,41872L,41873L,41874L,41875L,41876L,41877L,41878L,41879L,41880L,
93208 41881L,41882L,41883L,41884L,41885L,41886L,41887L,41888L,41889L,41890L,
93209 41891L,41892L,41893L,41894L,41895L,41896L,41897L,41898L,41899L,41900L,
93210 41901L,41902L,41903L,41904L,41905L,41906L,41907L,41908L,41909L,41910L,
93211 41911L,41912L,41913L,41914L,41915L,41916L,41917L,41918L,41919L,41920L,
93212 41921L,41922L,41923L,41924L,41925L,41926L,41927L,41928L,41929L,41930L,
93213 41931L,41932L,41933L,41934L,41935L,41936L,41937L,41938L,41939L,41940L,
93214 41941L,41942L,41943L,41944L,41945L,41946L,41947L,41948L,41949L,41950L,
93215 41951L,41952L,41953L,41954L,41955L,41956L,41957L,41958L,41959L,41960L,
93216 41961L,41962L,41963L,41964L,41965L,41966L,41967L,41968L,41969L,41970L,
93217 41971L,41972L,41973L,41974L,41975L,41976L,41977L,41978L,41979L,41980L,
93218 41981L,41982L,41983L,41984L,41985L,41986L,41987L,41988L,41989L,41990L,
93219 41991L,41992L,41993L,41994L,41995L,41996L,41997L,41998L,41999L,42000L,
93220 42001L,42002L,42003L,42004L,42005L,42006L,42007L,42008L,42009L,42010L,
93221 42011L,42012L,42013L,42014L,42015L,42016L,42017L,42018L,42019L,42020L,
93222 42021L,42022L,42023L,42024L,42025L,42026L,42027L,42028L,42029L,42030L,
93223 42031L,42032L,42033L,42034L,42035L,42036L,42037L,42038L,42039L,42040L,
93224 42041L,42042L,42043L,42044L,42045L,42046L,42047L,42048L,42049L,42050L,
93225 42051L,42052L,42053L,42054L,42055L,42056L,42057L,42058L,42059L,42060L,
93226 42061L,42062L,42063L,42064L,42065L,42066L,42067L,42068L,42069L,42070L,
93227 42071L,42072L,42073L,42074L,42075L,42076L,42077L,42078L,42079L,42080L,
93228 42081L,42082L,42083L,42084L,42085L,42086L,42087L,42088L,42089L,42090L,
93229 42091L,42092L,42093L,42094L,42095L,42096L,42097L,42098L,42099L,42100L,
93230 42101L,42102L,42103L,42104L,42105L,42106L,42107L,42108L,42109L,42110L,
93231 42111L,42112L,42113L,42114L,42115L,42116L,42117L,42118L,42119L,42120L,
93232 42121L,42122L,42123L,42124L,42125L,42126L,42127L,42128L,42129L,42130L,
93233 42131L,42132L,42133L,42134L,42135L,42136L,42137L,42138L,42139L,42140L,
93234 42141L,42142L,42143L,42144L,42145L,42146L,42147L,42148L,42149L,42150L,
93235 42151L,42152L,42153L,42154L,42155L,42156L,42157L,42158L,42159L,42160L,
93236 42161L,42162L,42163L,42164L,42165L,42166L,42167L,42168L,42169L,42170L,
93237 42171L,42172L,42173L,42174L,42175L,42176L,42177L,42178L,42179L,42180L,
93238 42181L,42182L,42183L,42184L,42185L,42186L,42187L,42188L,42189L,42190L,
93239 42191L,42192L,42193L,42194L,42195L,42196L,42197L,42198L,42199L,42200L,
93240 42201L,42202L,42203L,42204L,42205L,42206L,42207L,42208L,42209L,42210L,
93241 42211L,42212L,42213L,42214L,42215L,42216L,42217L,42218L,42219L,42220L,
93242 42221L,42222L,42223L,42224L,42225L,42226L,42227L,42228L,42229L,42230L,
93243 42231L,42232L,42233L,42234L,42235L,42236L,42237L,42238L,42239L,42240L,
93244 42241L,42242L,42243L,42244L,42245L,42246L,42247L,42248L,42249L,42250L,
93245 42251L,42252L,42253L,42254L,42255L,42256L,42257L,42258L,42259L,42260L,
93246 42261L,42262L,42263L,42264L,42265L,42266L,42267L,42268L,42269L,42270L,
93247 42271L,42272L,42273L,42274L,42275L,42276L,42277L,42278L,42279L,42280L,
93248 42281L,42282L,42283L,42284L,42285L,42286L,42287L,42288L,42289L,42290L,
93249 42291L,42292L,42293L,42294L,42295L,42296L,42297L,42298L,42299L,42300L,
93250 42301L,42302L,42303L,42304L,42305L,42306L,42307L,42308L,42309L,42310L,
93251 42311L,42312L,42313L,42314L,42315L,42316L,42317L,42318L,42319L,42320L,
93252 42321L,42322L,42323L,42324L,42325L,42326L,42327L,42328L,42329L,42330L,
93253 42331L,42332L,42333L,42334L,42335L,42336L,42337L,42338L,42339L,42340L,
93254 42341L,42342L,42343L,42344L,42345L,42346L,42347L,42348L,42349L,42350L,
93255 42351L,42352L,42353L,42354L,42355L,42356L,42357L,42358L,42359L,42360L,
93256 42361L,42362L,42363L,42364L,42365L,42366L,42367L,42368L,42369L,42370L,
93257 42371L,42372L,42373L,42374L,42375L,42376L,42377L,42378L,42379L,42380L,
93258 42381L,42382L,42383L,42384L,42385L,42386L,42387L,42388L,42389L,42390L,
93259 42391L,42392L,42393L,42394L,42395L,42396L,42397L,42398L,42399L,42400L,
93260 42401L,42402L,42403L,42404L,42405L,42406L,42407L,42408L,42409L,42410L,
93261 42411L,42412L,42413L,42414L,42415L,42416L,42417L,42418L,42419L,42420L,
93262 42421L,42422L,42423L,42424L,42425L,42426L,42427L,42428L,42429L,42430L,
93263 42431L,42432L,42433L,42434L,42435L,42436L,42437L,42438L,42439L,42440L,
93264 42441L,42442L,42443L,42444L,42445L,42446L,42447L,42448L,42449L,42450L,
93265 42451L,42452L,42453L,42454L,42455L,42456L,42457L,42458L,42459L,42460L,
93266 42461L,42462L,42463L,42464L,42465L,42466L,42467L,42468L,42469L,42470L,
93267 42471L,42472L,42473L,42474L,42475L,42476L,42477L,42478L,42479L,42480L,
93268 42481L,42482L,42483L,42484L,42485L,42486L,42487L,42488L,42489L,42490L,
93269 42491L,42492L,42493L,42494L,42495L,42496L,42497L,42498L,42499L,42500L,
93270 42501L,42502L,42503L,42504L,42505L,42506L,42507L,42508L,42509L,42510L,
93271 42511L,42512L,42513L,42514L,42515L,42516L,42517L,42518L,42519L,42520L,
93272 42521L,42522L,42523L,42524L,42525L,42526L,42527L,42528L,42529L,42530L,
93273 42531L,42532L,42533L,42534L,42535L,42536L,42537L,42538L,42539L,42540L,
93274 42541L,42542L,42543L,42544L,42545L,42546L,42547L,42548L,42549L,42550L,
93275 42551L,42552L,42553L,42554L,42555L,42556L,42557L,42558L,42559L,42560L,
93276 42560L,42562L,42562L,42564L,42564L,42566L,42566L,42568L,42568L,42570L,
93277 42570L,42572L,42572L,42574L,42574L,42576L,42576L,42578L,42578L,42580L,
93278 42580L,42582L,42582L,42584L,42584L,42586L,42586L,42588L,42588L,42590L,
93279 42590L,42592L,42592L,42594L,42594L,42596L,42596L,42598L,42598L,42600L,
93280 42600L,42602L,42602L,42604L,42604L,42606L,42607L,42608L,42609L,42610L,
93281 42611L,42612L,42613L,42614L,42615L,42616L,42617L,42618L,42619L,42620L,
93282 42621L,42622L,42623L,42624L,42624L,42626L,42626L,42628L,42628L,42630L,
93283 42630L,42632L,42632L,42634L,42634L,42636L,42636L,42638L,42638L,42640L,
93284 42640L,42642L,42642L,42644L,42644L,42646L,42646L,42648L,42648L,42650L,
93285 42650L,42652L,42653L,42654L,42655L,42656L,42657L,42658L,42659L,42660L,
93286 42661L,42662L,42663L,42664L,42665L,42666L,42667L,42668L,42669L,42670L,
93287 42671L,42672L,42673L,42674L,42675L,42676L,42677L,42678L,42679L,42680L,
93288 42681L,42682L,42683L,42684L,42685L,42686L,42687L,42688L,42689L,42690L,
93289 42691L,42692L,42693L,42694L,42695L,42696L,42697L,42698L,42699L,42700L,
93290 42701L,42702L,42703L,42704L,42705L,42706L,42707L,42708L,42709L,42710L,
93291 42711L,42712L,42713L,42714L,42715L,42716L,42717L,42718L,42719L,42720L,
93292 42721L,42722L,42723L,42724L,42725L,42726L,42727L,42728L,42729L,42730L,
93293 42731L,42732L,42733L,42734L,42735L,42736L,42737L,42738L,42739L,42740L,
93294 42741L,42742L,42743L,42744L,42745L,42746L,42747L,42748L,42749L,42750L,
93295 42751L,42752L,42753L,42754L,42755L,42756L,42757L,42758L,42759L,42760L,
93296 42761L,42762L,42763L,42764L,42765L,42766L,42767L,42768L,42769L,42770L,
93297 42771L,42772L,42773L,42774L,42775L,42776L,42777L,42778L,42779L,42780L,
93298 42781L,42782L,42783L,42784L,42785L,42786L,42786L,42788L,42788L,42790L,
93299 42790L,42792L,42792L,42794L,42794L,42796L,42796L,42798L,42798L,42800L,
93300 42801L,42802L,42802L,42804L,42804L,42806L,42806L,42808L,42808L,42810L,
93301 42810L,42812L,42812L,42814L,42814L,42816L,42816L,42818L,42818L,42820L,
93302 42820L,42822L,42822L,42824L,42824L,42826L,42826L,42828L,42828L,42830L,
93303 42830L,42832L,42832L,42834L,42834L,42836L,42836L,42838L,42838L,42840L,
93304 42840L,42842L,42842L,42844L,42844L,42846L,42846L,42848L,42848L,42850L,
93305 42850L,42852L,42852L,42854L,42854L,42856L,42856L,42858L,42858L,42860L,
93306 42860L,42862L,42862L,42864L,42865L,42866L,42867L,42868L,42869L,42870L,
93307 42871L,42872L,42873L,42873L,42875L,42875L,42877L,42878L,42878L,42880L,
93308 42880L,42882L,42882L,42884L,42884L,42886L,42886L,42888L,42889L,42890L,
93309 42891L,42891L,42893L,42894L,42895L,42896L,42896L,42898L,42898L,42900L,
93310 42901L,42902L,42902L,42904L,42904L,42906L,42906L,42908L,42908L,42910L,
93311 42910L,42912L,42912L,42914L,42914L,42916L,42916L,42918L,42918L,42920L,
93312 42920L,42922L,42923L,42924L,42925L,42926L,42927L,42928L,42929L,42930L,
93313 42931L,42932L,42932L,42934L,42934L,42936L,42937L,42938L,42939L,42940L,
93314 42941L,42942L,42943L,42944L,42945L,42946L,42947L,42948L,42949L,42950L,
93315 42951L,42952L,42953L,42954L,42955L,42956L,42957L,42958L,42959L,42960L,
93316 42961L,42962L,42963L,42964L,42965L,42966L,42967L,42968L,42969L,42970L,
93317 42971L,42972L,42973L,42974L,42975L,42976L,42977L,42978L,42979L,42980L,
93318 42981L,42982L,42983L,42984L,42985L,42986L,42987L,42988L,42989L,42990L,
93319 42991L,42992L,42993L,42994L,42995L,42996L,42997L,42998L,42999L,43000L,
93320 43001L,43002L,43003L,43004L,43005L,43006L,43007L,43008L,43009L,43010L,
93321 43011L,43012L,43013L,43014L,43015L,43016L,43017L,43018L,43019L,43020L,
93322 43021L,43022L,43023L,43024L,43025L,43026L,43027L,43028L,43029L,43030L,
93323 43031L,43032L,43033L,43034L,43035L,43036L,43037L,43038L,43039L,43040L,
93324 43041L,43042L,43043L,43044L,43045L,43046L,43047L,43048L,43049L,43050L,
93325 43051L,43052L,43053L,43054L,43055L,43056L,43057L,43058L,43059L,43060L,
93326 43061L,43062L,43063L,43064L,43065L,43066L,43067L,43068L,43069L,43070L,
93327 43071L,43072L,43073L,43074L,43075L,43076L,43077L,43078L,43079L,43080L,
93328 43081L,43082L,43083L,43084L,43085L,43086L,43087L,43088L,43089L,43090L,
93329 43091L,43092L,43093L,43094L,43095L,43096L,43097L,43098L,43099L,43100L,
93330 43101L,43102L,43103L,43104L,43105L,43106L,43107L,43108L,43109L,43110L,
93331 43111L,43112L,43113L,43114L,43115L,43116L,43117L,43118L,43119L,43120L,
93332 43121L,43122L,43123L,43124L,43125L,43126L,43127L,43128L,43129L,43130L,
93333 43131L,43132L,43133L,43134L,43135L,43136L,43137L,43138L,43139L,43140L,
93334 43141L,43142L,43143L,43144L,43145L,43146L,43147L,43148L,43149L,43150L,
93335 43151L,43152L,43153L,43154L,43155L,43156L,43157L,43158L,43159L,43160L,
93336 43161L,43162L,43163L,43164L,43165L,43166L,43167L,43168L,43169L,43170L,
93337 43171L,43172L,43173L,43174L,43175L,43176L,43177L,43178L,43179L,43180L,
93338 43181L,43182L,43183L,43184L,43185L,43186L,43187L,43188L,43189L,43190L,
93339 43191L,43192L,43193L,43194L,43195L,43196L,43197L,43198L,43199L,43200L,
93340 43201L,43202L,43203L,43204L,43205L,43206L,43207L,43208L,43209L,43210L,
93341 43211L,43212L,43213L,43214L,43215L,43216L,43217L,43218L,43219L,43220L,
93342 43221L,43222L,43223L,43224L,43225L,43226L,43227L,43228L,43229L,43230L,
93343 43231L,43232L,43233L,43234L,43235L,43236L,43237L,43238L,43239L,43240L,
93344 43241L,43242L,43243L,43244L,43245L,43246L,43247L,43248L,43249L,43250L,
93345 43251L,43252L,43253L,43254L,43255L,43256L,43257L,43258L,43259L,43260L,
93346 43261L,43262L,43263L,43264L,43265L,43266L,43267L,43268L,43269L,43270L,
93347 43271L,43272L,43273L,43274L,43275L,43276L,43277L,43278L,43279L,43280L,
93348 43281L,43282L,43283L,43284L,43285L,43286L,43287L,43288L,43289L,43290L,
93349 43291L,43292L,43293L,43294L,43295L,43296L,43297L,43298L,43299L,43300L,
93350 43301L,43302L,43303L,43304L,43305L,43306L,43307L,43308L,43309L,43310L,
93351 43311L,43312L,43313L,43314L,43315L,43316L,43317L,43318L,43319L,43320L,
93352 43321L,43322L,43323L,43324L,43325L,43326L,43327L,43328L,43329L,43330L,
93353 43331L,43332L,43333L,43334L,43335L,43336L,43337L,43338L,43339L,43340L,
93354 43341L,43342L,43343L,43344L,43345L,43346L,43347L,43348L,43349L,43350L,
93355 43351L,43352L,43353L,43354L,43355L,43356L,43357L,43358L,43359L,43360L,
93356 43361L,43362L,43363L,43364L,43365L,43366L,43367L,43368L,43369L,43370L,
93357 43371L,43372L,43373L,43374L,43375L,43376L,43377L,43378L,43379L,43380L,
93358 43381L,43382L,43383L,43384L,43385L,43386L,43387L,43388L,43389L,43390L,
93359 43391L,43392L,43393L,43394L,43395L,43396L,43397L,43398L,43399L,43400L,
93360 43401L,43402L,43403L,43404L,43405L,43406L,43407L,43408L,43409L,43410L,
93361 43411L,43412L,43413L,43414L,43415L,43416L,43417L,43418L,43419L,43420L,
93362 43421L,43422L,43423L,43424L,43425L,43426L,43427L,43428L,43429L,43430L,
93363 43431L,43432L,43433L,43434L,43435L,43436L,43437L,43438L,43439L,43440L,
93364 43441L,43442L,43443L,43444L,43445L,43446L,43447L,43448L,43449L,43450L,
93365 43451L,43452L,43453L,43454L,43455L,43456L,43457L,43458L,43459L,43460L,
93366 43461L,43462L,43463L,43464L,43465L,43466L,43467L,43468L,43469L,43470L,
93367 43471L,43472L,43473L,43474L,43475L,43476L,43477L,43478L,43479L,43480L,
93368 43481L,43482L,43483L,43484L,43485L,43486L,43487L,43488L,43489L,43490L,
93369 43491L,43492L,43493L,43494L,43495L,43496L,43497L,43498L,43499L,43500L,
93370 43501L,43502L,43503L,43504L,43505L,43506L,43507L,43508L,43509L,43510L,
93371 43511L,43512L,43513L,43514L,43515L,43516L,43517L,43518L,43519L,43520L,
93372 43521L,43522L,43523L,43524L,43525L,43526L,43527L,43528L,43529L,43530L,
93373 43531L,43532L,43533L,43534L,43535L,43536L,43537L,43538L,43539L,43540L,
93374 43541L,43542L,43543L,43544L,43545L,43546L,43547L,43548L,43549L,43550L,
93375 43551L,43552L,43553L,43554L,43555L,43556L,43557L,43558L,43559L,43560L,
93376 43561L,43562L,43563L,43564L,43565L,43566L,43567L,43568L,43569L,43570L,
93377 43571L,43572L,43573L,43574L,43575L,43576L,43577L,43578L,43579L,43580L,
93378 43581L,43582L,43583L,43584L,43585L,43586L,43587L,43588L,43589L,43590L,
93379 43591L,43592L,43593L,43594L,43595L,43596L,43597L,43598L,43599L,43600L,
93380 43601L,43602L,43603L,43604L,43605L,43606L,43607L,43608L,43609L,43610L,
93381 43611L,43612L,43613L,43614L,43615L,43616L,43617L,43618L,43619L,43620L,
93382 43621L,43622L,43623L,43624L,43625L,43626L,43627L,43628L,43629L,43630L,
93383 43631L,43632L,43633L,43634L,43635L,43636L,43637L,43638L,43639L,43640L,
93384 43641L,43642L,43643L,43644L,43645L,43646L,43647L,43648L,43649L,43650L,
93385 43651L,43652L,43653L,43654L,43655L,43656L,43657L,43658L,43659L,43660L,
93386 43661L,43662L,43663L,43664L,43665L,43666L,43667L,43668L,43669L,43670L,
93387 43671L,43672L,43673L,43674L,43675L,43676L,43677L,43678L,43679L,43680L,
93388 43681L,43682L,43683L,43684L,43685L,43686L,43687L,43688L,43689L,43690L,
93389 43691L,43692L,43693L,43694L,43695L,43696L,43697L,43698L,43699L,43700L,
93390 43701L,43702L,43703L,43704L,43705L,43706L,43707L,43708L,43709L,43710L,
93391 43711L,43712L,43713L,43714L,43715L,43716L,43717L,43718L,43719L,43720L,
93392 43721L,43722L,43723L,43724L,43725L,43726L,43727L,43728L,43729L,43730L,
93393 43731L,43732L,43733L,43734L,43735L,43736L,43737L,43738L,43739L,43740L,
93394 43741L,43742L,43743L,43744L,43745L,43746L,43747L,43748L,43749L,43750L,
93395 43751L,43752L,43753L,43754L,43755L,43756L,43757L,43758L,43759L,43760L,
93396 43761L,43762L,43763L,43764L,43765L,43766L,43767L,43768L,43769L,43770L,
93397 43771L,43772L,43773L,43774L,43775L,43776L,43777L,43778L,43779L,43780L,
93398 43781L,43782L,43783L,43784L,43785L,43786L,43787L,43788L,43789L,43790L,
93399 43791L,43792L,43793L,43794L,43795L,43796L,43797L,43798L,43799L,43800L,
93400 43801L,43802L,43803L,43804L,43805L,43806L,43807L,43808L,43809L,43810L,
93401 43811L,43812L,43813L,43814L,43815L,43816L,43817L,43818L,43819L,43820L,
93402 43821L,43822L,43823L,43824L,43825L,43826L,43827L,43828L,43829L,43830L,
93403 43831L,43832L,43833L,43834L,43835L,43836L,43837L,43838L,43839L,43840L,
93404 43841L,43842L,43843L,43844L,43845L,43846L,43847L,43848L,43849L,43850L,
93405 43851L,43852L,43853L,43854L,43855L,43856L,43857L,43858L,42931L,43860L,
93406 43861L,43862L,43863L,43864L,43865L,43866L,43867L,43868L,43869L,43870L,
93407 43871L,43872L,43873L,43874L,43875L,43876L,43877L,43878L,43879L,43880L,
93408 43881L,43882L,43883L,43884L,43885L,43886L,43887L,5024,5025,5026,5027,5028,
93409 5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,
93410 5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,
93411 5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,
93412 5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,
93413 5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,
93414 43968L,43969L,43970L,43971L,43972L,43973L,43974L,43975L,43976L,43977L,
93415 43978L,43979L,43980L,43981L,43982L,43983L,43984L,43985L,43986L,43987L,
93416 43988L,43989L,43990L,43991L,43992L,43993L,43994L,43995L,43996L,43997L,
93417 43998L,43999L,44000L,44001L,44002L,44003L,44004L,44005L,44006L,44007L,
93418 44008L,44009L,44010L,44011L,44012L,44013L,44014L,44015L,44016L,44017L,
93419 44018L,44019L,44020L,44021L,44022L,44023L,44024L,44025L,44026L,44027L,
93420 44028L,44029L,44030L,44031L,44032L,44033L,44034L,44035L,44036L,44037L,
93421 44038L,44039L,44040L,44041L,44042L,44043L,44044L,44045L,44046L,44047L,
93422 44048L,44049L,44050L,44051L,44052L,44053L,44054L,44055L,44056L,44057L,
93423 44058L,44059L,44060L,44061L,44062L,44063L,44064L,44065L,44066L,44067L,
93424 44068L,44069L,44070L,44071L,44072L,44073L,44074L,44075L,44076L,44077L,
93425 44078L,44079L,44080L,44081L,44082L,44083L,44084L,44085L,44086L,44087L,
93426 44088L,44089L,44090L,44091L,44092L,44093L,44094L,44095L,44096L,44097L,
93427 44098L,44099L,44100L,44101L,44102L,44103L,44104L,44105L,44106L,44107L,
93428 44108L,44109L,44110L,44111L,44112L,44113L,44114L,44115L,44116L,44117L,
93429 44118L,44119L,44120L,44121L,44122L,44123L,44124L,44125L,44126L,44127L,
93430 44128L,44129L,44130L,44131L,44132L,44133L,44134L,44135L,44136L,44137L,
93431 44138L,44139L,44140L,44141L,44142L,44143L,44144L,44145L,44146L,44147L,
93432 44148L,44149L,44150L,44151L,44152L,44153L,44154L,44155L,44156L,44157L,
93433 44158L,44159L,44160L,44161L,44162L,44163L,44164L,44165L,44166L,44167L,
93434 44168L,44169L,44170L,44171L,44172L,44173L,44174L,44175L,44176L,44177L,
93435 44178L,44179L,44180L,44181L,44182L,44183L,44184L,44185L,44186L,44187L,
93436 44188L,44189L,44190L,44191L,44192L,44193L,44194L,44195L,44196L,44197L,
93437 44198L,44199L,44200L,44201L,44202L,44203L,44204L,44205L,44206L,44207L,
93438 44208L,44209L,44210L,44211L,44212L,44213L,44214L,44215L,44216L,44217L,
93439 44218L,44219L,44220L,44221L,44222L,44223L,44224L,44225L,44226L,44227L,
93440 44228L,44229L,44230L,44231L,44232L,44233L,44234L,44235L,44236L,44237L,
93441 44238L,44239L,44240L,44241L,44242L,44243L,44244L,44245L,44246L,44247L,
93442 44248L,44249L,44250L,44251L,44252L,44253L,44254L,44255L,44256L,44257L,
93443 44258L,44259L,44260L,44261L,44262L,44263L,44264L,44265L,44266L,44267L,
93444 44268L,44269L,44270L,44271L,44272L,44273L,44274L,44275L,44276L,44277L,
93445 44278L,44279L,44280L,44281L,44282L,44283L,44284L,44285L,44286L,44287L,
93446 44288L,44289L,44290L,44291L,44292L,44293L,44294L,44295L,44296L,44297L,
93447 44298L,44299L,44300L,44301L,44302L,44303L,44304L,44305L,44306L,44307L,
93448 44308L,44309L,44310L,44311L,44312L,44313L,44314L,44315L,44316L,44317L,
93449 44318L,44319L,44320L,44321L,44322L,44323L,44324L,44325L,44326L,44327L,
93450 44328L,44329L,44330L,44331L,44332L,44333L,44334L,44335L,44336L,44337L,
93451 44338L,44339L,44340L,44341L,44342L,44343L,44344L,44345L,44346L,44347L,
93452 44348L,44349L,44350L,44351L,44352L,44353L,44354L,44355L,44356L,44357L,
93453 44358L,44359L,44360L,44361L,44362L,44363L,44364L,44365L,44366L,44367L,
93454 44368L,44369L,44370L,44371L,44372L,44373L,44374L,44375L,44376L,44377L,
93455 44378L,44379L,44380L,44381L,44382L,44383L,44384L,44385L,44386L,44387L,
93456 44388L,44389L,44390L,44391L,44392L,44393L,44394L,44395L,44396L,44397L,
93457 44398L,44399L,44400L,44401L,44402L,44403L,44404L,44405L,44406L,44407L,
93458 44408L,44409L,44410L,44411L,44412L,44413L,44414L,44415L,44416L,44417L,
93459 44418L,44419L,44420L,44421L,44422L,44423L,44424L,44425L,44426L,44427L,
93460 44428L,44429L,44430L,44431L,44432L,44433L,44434L,44435L,44436L,44437L,
93461 44438L,44439L,44440L,44441L,44442L,44443L,44444L,44445L,44446L,44447L,
93462 44448L,44449L,44450L,44451L,44452L,44453L,44454L,44455L,44456L,44457L,
93463 44458L,44459L,44460L,44461L,44462L,44463L,44464L,44465L,44466L,44467L,
93464 44468L,44469L,44470L,44471L,44472L,44473L,44474L,44475L,44476L,44477L,
93465 44478L,44479L,44480L,44481L,44482L,44483L,44484L,44485L,44486L,44487L,
93466 44488L,44489L,44490L,44491L,44492L,44493L,44494L,44495L,44496L,44497L,
93467 44498L,44499L,44500L,44501L,44502L,44503L,44504L,44505L,44506L,44507L,
93468 44508L,44509L,44510L,44511L,44512L,44513L,44514L,44515L,44516L,44517L,
93469 44518L,44519L,44520L,44521L,44522L,44523L,44524L,44525L,44526L,44527L,
93470 44528L,44529L,44530L,44531L,44532L,44533L,44534L,44535L,44536L,44537L,
93471 44538L,44539L,44540L,44541L,44542L,44543L,44544L,44545L,44546L,44547L,
93472 44548L,44549L,44550L,44551L,44552L,44553L,44554L,44555L,44556L,44557L,
93473 44558L,44559L,44560L,44561L,44562L,44563L,44564L,44565L,44566L,44567L,
93474 44568L,44569L,44570L,44571L,44572L,44573L,44574L,44575L,44576L,44577L,
93475 44578L,44579L,44580L,44581L,44582L,44583L,44584L,44585L,44586L,44587L,
93476 44588L,44589L,44590L,44591L,44592L,44593L,44594L,44595L,44596L,44597L,
93477 44598L,44599L,44600L,44601L,44602L,44603L,44604L,44605L,44606L,44607L,
93478 44608L,44609L,44610L,44611L,44612L,44613L,44614L,44615L,44616L,44617L,
93479 44618L,44619L,44620L,44621L,44622L,44623L,44624L,44625L,44626L,44627L,
93480 44628L,44629L,44630L,44631L,44632L,44633L,44634L,44635L,44636L,44637L,
93481 44638L,44639L,44640L,44641L,44642L,44643L,44644L,44645L,44646L,44647L,
93482 44648L,44649L,44650L,44651L,44652L,44653L,44654L,44655L,44656L,44657L,
93483 44658L,44659L,44660L,44661L,44662L,44663L,44664L,44665L,44666L,44667L,
93484 44668L,44669L,44670L,44671L,44672L,44673L,44674L,44675L,44676L,44677L,
93485 44678L,44679L,44680L,44681L,44682L,44683L,44684L,44685L,44686L,44687L,
93486 44688L,44689L,44690L,44691L,44692L,44693L,44694L,44695L,44696L,44697L,
93487 44698L,44699L,44700L,44701L,44702L,44703L,44704L,44705L,44706L,44707L,
93488 44708L,44709L,44710L,44711L,44712L,44713L,44714L,44715L,44716L,44717L,
93489 44718L,44719L,44720L,44721L,44722L,44723L,44724L,44725L,44726L,44727L,
93490 44728L,44729L,44730L,44731L,44732L,44733L,44734L,44735L,44736L,44737L,
93491 44738L,44739L,44740L,44741L,44742L,44743L,44744L,44745L,44746L,44747L,
93492 44748L,44749L,44750L,44751L,44752L,44753L,44754L,44755L,44756L,44757L,
93493 44758L,44759L,44760L,44761L,44762L,44763L,44764L,44765L,44766L,44767L,
93494 44768L,44769L,44770L,44771L,44772L,44773L,44774L,44775L,44776L,44777L,
93495 44778L,44779L,44780L,44781L,44782L,44783L,44784L,44785L,44786L,44787L,
93496 44788L,44789L,44790L,44791L,44792L,44793L,44794L,44795L,44796L,44797L,
93497 44798L,44799L,44800L,44801L,44802L,44803L,44804L,44805L,44806L,44807L,
93498 44808L,44809L,44810L,44811L,44812L,44813L,44814L,44815L,44816L,44817L,
93499 44818L,44819L,44820L,44821L,44822L,44823L,44824L,44825L,44826L,44827L,
93500 44828L,44829L,44830L,44831L,44832L,44833L,44834L,44835L,44836L,44837L,
93501 44838L,44839L,44840L,44841L,44842L,44843L,44844L,44845L,44846L,44847L,
93502 44848L,44849L,44850L,44851L,44852L,44853L,44854L,44855L,44856L,44857L,
93503 44858L,44859L,44860L,44861L,44862L,44863L,44864L,44865L,44866L,44867L,
93504 44868L,44869L,44870L,44871L,44872L,44873L,44874L,44875L,44876L,44877L,
93505 44878L,44879L,44880L,44881L,44882L,44883L,44884L,44885L,44886L,44887L,
93506 44888L,44889L,44890L,44891L,44892L,44893L,44894L,44895L,44896L,44897L,
93507 44898L,44899L,44900L,44901L,44902L,44903L,44904L,44905L,44906L,44907L,
93508 44908L,44909L,44910L,44911L,44912L,44913L,44914L,44915L,44916L,44917L,
93509 44918L,44919L,44920L,44921L,44922L,44923L,44924L,44925L,44926L,44927L,
93510 44928L,44929L,44930L,44931L,44932L,44933L,44934L,44935L,44936L,44937L,
93511 44938L,44939L,44940L,44941L,44942L,44943L,44944L,44945L,44946L,44947L,
93512 44948L,44949L,44950L,44951L,44952L,44953L,44954L,44955L,44956L,44957L,
93513 44958L,44959L,44960L,44961L,44962L,44963L,44964L,44965L,44966L,44967L,
93514 44968L,44969L,44970L,44971L,44972L,44973L,44974L,44975L,44976L,44977L,
93515 44978L,44979L,44980L,44981L,44982L,44983L,44984L,44985L,44986L,44987L,
93516 44988L,44989L,44990L,44991L,44992L,44993L,44994L,44995L,44996L,44997L,
93517 44998L,44999L,45000L,45001L,45002L,45003L,45004L,45005L,45006L,45007L,
93518 45008L,45009L,45010L,45011L,45012L,45013L,45014L,45015L,45016L,45017L,
93519 45018L,45019L,45020L,45021L,45022L,45023L,45024L,45025L,45026L,45027L,
93520 45028L,45029L,45030L,45031L,45032L,45033L,45034L,45035L,45036L,45037L,
93521 45038L,45039L,45040L,45041L,45042L,45043L,45044L,45045L,45046L,45047L,
93522 45048L,45049L,45050L,45051L,45052L,45053L,45054L,45055L,45056L,45057L,
93523 45058L,45059L,45060L,45061L,45062L,45063L,45064L,45065L,45066L,45067L,
93524 45068L,45069L,45070L,45071L,45072L,45073L,45074L,45075L,45076L,45077L,
93525 45078L,45079L,45080L,45081L,45082L,45083L,45084L,45085L,45086L,45087L,
93526 45088L,45089L,45090L,45091L,45092L,45093L,45094L,45095L,45096L,45097L,
93527 45098L,45099L,45100L,45101L,45102L,45103L,45104L,45105L,45106L,45107L,
93528 45108L,45109L,45110L,45111L,45112L,45113L,45114L,45115L,45116L,45117L,
93529 45118L,45119L,45120L,45121L,45122L,45123L,45124L,45125L,45126L,45127L,
93530 45128L,45129L,45130L,45131L,45132L,45133L,45134L,45135L,45136L,45137L,
93531 45138L,45139L,45140L,45141L,45142L,45143L,45144L,45145L,45146L,45147L,
93532 45148L,45149L,45150L,45151L,45152L,45153L,45154L,45155L,45156L,45157L,
93533 45158L,45159L,45160L,45161L,45162L,45163L,45164L,45165L,45166L,45167L,
93534 45168L,45169L,45170L,45171L,45172L,45173L,45174L,45175L,45176L,45177L,
93535 45178L,45179L,45180L,45181L,45182L,45183L,45184L,45185L,45186L,45187L,
93536 45188L,45189L,45190L,45191L,45192L,45193L,45194L,45195L,45196L,45197L,
93537 45198L,45199L,45200L,45201L,45202L,45203L,45204L,45205L,45206L,45207L,
93538 45208L,45209L,45210L,45211L,45212L,45213L,45214L,45215L,45216L,45217L,
93539 45218L,45219L,45220L,45221L,45222L,45223L,45224L,45225L,45226L,45227L,
93540 45228L,45229L,45230L,45231L,45232L,45233L,45234L,45235L,45236L,45237L,
93541 45238L,45239L,45240L,45241L,45242L,45243L,45244L,45245L,45246L,45247L,
93542 45248L,45249L,45250L,45251L,45252L,45253L,45254L,45255L,45256L,45257L,
93543 45258L,45259L,45260L,45261L,45262L,45263L,45264L,45265L,45266L,45267L,
93544 45268L,45269L,45270L,45271L,45272L,45273L,45274L,45275L,45276L,45277L,
93545 45278L,45279L,45280L,45281L,45282L,45283L,45284L,45285L,45286L,45287L,
93546 45288L,45289L,45290L,45291L,45292L,45293L,45294L,45295L,45296L,45297L,
93547 45298L,45299L,45300L,45301L,45302L,45303L,45304L,45305L,45306L,45307L,
93548 45308L,45309L,45310L,45311L,45312L,45313L,45314L,45315L,45316L,45317L,
93549 45318L,45319L,45320L,45321L,45322L,45323L,45324L,45325L,45326L,45327L,
93550 45328L,45329L,45330L,45331L,45332L,45333L,45334L,45335L,45336L,45337L,
93551 45338L,45339L,45340L,45341L,45342L,45343L,45344L,45345L,45346L,45347L,
93552 45348L,45349L,45350L,45351L,45352L,45353L,45354L,45355L,45356L,45357L,
93553 45358L,45359L,45360L,45361L,45362L,45363L,45364L,45365L,45366L,45367L,
93554 45368L,45369L,45370L,45371L,45372L,45373L,45374L,45375L,45376L,45377L,
93555 45378L,45379L,45380L,45381L,45382L,45383L,45384L,45385L,45386L,45387L,
93556 45388L,45389L,45390L,45391L,45392L,45393L,45394L,45395L,45396L,45397L,
93557 45398L,45399L,45400L,45401L,45402L,45403L,45404L,45405L,45406L,45407L,
93558 45408L,45409L,45410L,45411L,45412L,45413L,45414L,45415L,45416L,45417L,
93559 45418L,45419L,45420L,45421L,45422L,45423L,45424L,45425L,45426L,45427L,
93560 45428L,45429L,45430L,45431L,45432L,45433L,45434L,45435L,45436L,45437L,
93561 45438L,45439L,45440L,45441L,45442L,45443L,45444L,45445L,45446L,45447L,
93562 45448L,45449L,45450L,45451L,45452L,45453L,45454L,45455L,45456L,45457L,
93563 45458L,45459L,45460L,45461L,45462L,45463L,45464L,45465L,45466L,45467L,
93564 45468L,45469L,45470L,45471L,45472L,45473L,45474L,45475L,45476L,45477L,
93565 45478L,45479L,45480L,45481L,45482L,45483L,45484L,45485L,45486L,45487L,
93566 45488L,45489L,45490L,45491L,45492L,45493L,45494L,45495L,45496L,45497L,
93567 45498L,45499L,45500L,45501L,45502L,45503L,45504L,45505L,45506L,45507L,
93568 45508L,45509L,45510L,45511L,45512L,45513L,45514L,45515L,45516L,45517L,
93569 45518L,45519L,45520L,45521L,45522L,45523L,45524L,45525L,45526L,45527L,
93570 45528L,45529L,45530L,45531L,45532L,45533L,45534L,45535L,45536L,45537L,
93571 45538L,45539L,45540L,45541L,45542L,45543L,45544L,45545L,45546L,45547L,
93572 45548L,45549L,45550L,45551L,45552L,45553L,45554L,45555L,45556L,45557L,
93573 45558L,45559L,45560L,45561L,45562L,45563L,45564L,45565L,45566L,45567L,
93574 45568L,45569L,45570L,45571L,45572L,45573L,45574L,45575L,45576L,45577L,
93575 45578L,45579L,45580L,45581L,45582L,45583L,45584L,45585L,45586L,45587L,
93576 45588L,45589L,45590L,45591L,45592L,45593L,45594L,45595L,45596L,45597L,
93577 45598L,45599L,45600L,45601L,45602L,45603L,45604L,45605L,45606L,45607L,
93578 45608L,45609L,45610L,45611L,45612L,45613L,45614L,45615L,45616L,45617L,
93579 45618L,45619L,45620L,45621L,45622L,45623L,45624L,45625L,45626L,45627L,
93580 45628L,45629L,45630L,45631L,45632L,45633L,45634L,45635L,45636L,45637L,
93581 45638L,45639L,45640L,45641L,45642L,45643L,45644L,45645L,45646L,45647L,
93582 45648L,45649L,45650L,45651L,45652L,45653L,45654L,45655L,45656L,45657L,
93583 45658L,45659L,45660L,45661L,45662L,45663L,45664L,45665L,45666L,45667L,
93584 45668L,45669L,45670L,45671L,45672L,45673L,45674L,45675L,45676L,45677L,
93585 45678L,45679L,45680L,45681L,45682L,45683L,45684L,45685L,45686L,45687L,
93586 45688L,45689L,45690L,45691L,45692L,45693L,45694L,45695L,45696L,45697L,
93587 45698L,45699L,45700L,45701L,45702L,45703L,45704L,45705L,45706L,45707L,
93588 45708L,45709L,45710L,45711L,45712L,45713L,45714L,45715L,45716L,45717L,
93589 45718L,45719L,45720L,45721L,45722L,45723L,45724L,45725L,45726L,45727L,
93590 45728L,45729L,45730L,45731L,45732L,45733L,45734L,45735L,45736L,45737L,
93591 45738L,45739L,45740L,45741L,45742L,45743L,45744L,45745L,45746L,45747L,
93592 45748L,45749L,45750L,45751L,45752L,45753L,45754L,45755L,45756L,45757L,
93593 45758L,45759L,45760L,45761L,45762L,45763L,45764L,45765L,45766L,45767L,
93594 45768L,45769L,45770L,45771L,45772L,45773L,45774L,45775L,45776L,45777L,
93595 45778L,45779L,45780L,45781L,45782L,45783L,45784L,45785L,45786L,45787L,
93596 45788L,45789L,45790L,45791L,45792L,45793L,45794L,45795L,45796L,45797L,
93597 45798L,45799L,45800L,45801L,45802L,45803L,45804L,45805L,45806L,45807L,
93598 45808L,45809L,45810L,45811L,45812L,45813L,45814L,45815L,45816L,45817L,
93599 45818L,45819L,45820L,45821L,45822L,45823L,45824L,45825L,45826L,45827L,
93600 45828L,45829L,45830L,45831L,45832L,45833L,45834L,45835L,45836L,45837L,
93601 45838L,45839L,45840L,45841L,45842L,45843L,45844L,45845L,45846L,45847L,
93602 45848L,45849L,45850L,45851L,45852L,45853L,45854L,45855L,45856L,45857L,
93603 45858L,45859L,45860L,45861L,45862L,45863L,45864L,45865L,45866L,45867L,
93604 45868L,45869L,45870L,45871L,45872L,45873L,45874L,45875L,45876L,45877L,
93605 45878L,45879L,45880L,45881L,45882L,45883L,45884L,45885L,45886L,45887L,
93606 45888L,45889L,45890L,45891L,45892L,45893L,45894L,45895L,45896L,45897L,
93607 45898L,45899L,45900L,45901L,45902L,45903L,45904L,45905L,45906L,45907L,
93608 45908L,45909L,45910L,45911L,45912L,45913L,45914L,45915L,45916L,45917L,
93609 45918L,45919L,45920L,45921L,45922L,45923L,45924L,45925L,45926L,45927L,
93610 45928L,45929L,45930L,45931L,45932L,45933L,45934L,45935L,45936L,45937L,
93611 45938L,45939L,45940L,45941L,45942L,45943L,45944L,45945L,45946L,45947L,
93612 45948L,45949L,45950L,45951L,45952L,45953L,45954L,45955L,45956L,45957L,
93613 45958L,45959L,45960L,45961L,45962L,45963L,45964L,45965L,45966L,45967L,
93614 45968L,45969L,45970L,45971L,45972L,45973L,45974L,45975L,45976L,45977L,
93615 45978L,45979L,45980L,45981L,45982L,45983L,45984L,45985L,45986L,45987L,
93616 45988L,45989L,45990L,45991L,45992L,45993L,45994L,45995L,45996L,45997L,
93617 45998L,45999L,46000L,46001L,46002L,46003L,46004L,46005L,46006L,46007L,
93618 46008L,46009L,46010L,46011L,46012L,46013L,46014L,46015L,46016L,46017L,
93619 46018L,46019L,46020L,46021L,46022L,46023L,46024L,46025L,46026L,46027L,
93620 46028L,46029L,46030L,46031L,46032L,46033L,46034L,46035L,46036L,46037L,
93621 46038L,46039L,46040L,46041L,46042L,46043L,46044L,46045L,46046L,46047L,
93622 46048L,46049L,46050L,46051L,46052L,46053L,46054L,46055L,46056L,46057L,
93623 46058L,46059L,46060L,46061L,46062L,46063L,46064L,46065L,46066L,46067L,
93624 46068L,46069L,46070L,46071L,46072L,46073L,46074L,46075L,46076L,46077L,
93625 46078L,46079L,46080L,46081L,46082L,46083L,46084L,46085L,46086L,46087L,
93626 46088L,46089L,46090L,46091L,46092L,46093L,46094L,46095L,46096L,46097L,
93627 46098L,46099L,46100L,46101L,46102L,46103L,46104L,46105L,46106L,46107L,
93628 46108L,46109L,46110L,46111L,46112L,46113L,46114L,46115L,46116L,46117L,
93629 46118L,46119L,46120L,46121L,46122L,46123L,46124L,46125L,46126L,46127L,
93630 46128L,46129L,46130L,46131L,46132L,46133L,46134L,46135L,46136L,46137L,
93631 46138L,46139L,46140L,46141L,46142L,46143L,46144L,46145L,46146L,46147L,
93632 46148L,46149L,46150L,46151L,46152L,46153L,46154L,46155L,46156L,46157L,
93633 46158L,46159L,46160L,46161L,46162L,46163L,46164L,46165L,46166L,46167L,
93634 46168L,46169L,46170L,46171L,46172L,46173L,46174L,46175L,46176L,46177L,
93635 46178L,46179L,46180L,46181L,46182L,46183L,46184L,46185L,46186L,46187L,
93636 46188L,46189L,46190L,46191L,46192L,46193L,46194L,46195L,46196L,46197L,
93637 46198L,46199L,46200L,46201L,46202L,46203L,46204L,46205L,46206L,46207L,
93638 46208L,46209L,46210L,46211L,46212L,46213L,46214L,46215L,46216L,46217L,
93639 46218L,46219L,46220L,46221L,46222L,46223L,46224L,46225L,46226L,46227L,
93640 46228L,46229L,46230L,46231L,46232L,46233L,46234L,46235L,46236L,46237L,
93641 46238L,46239L,46240L,46241L,46242L,46243L,46244L,46245L,46246L,46247L,
93642 46248L,46249L,46250L,46251L,46252L,46253L,46254L,46255L,46256L,46257L,
93643 46258L,46259L,46260L,46261L,46262L,46263L,46264L,46265L,46266L,46267L,
93644 46268L,46269L,46270L,46271L,46272L,46273L,46274L,46275L,46276L,46277L,
93645 46278L,46279L,46280L,46281L,46282L,46283L,46284L,46285L,46286L,46287L,
93646 46288L,46289L,46290L,46291L,46292L,46293L,46294L,46295L,46296L,46297L,
93647 46298L,46299L,46300L,46301L,46302L,46303L,46304L,46305L,46306L,46307L,
93648 46308L,46309L,46310L,46311L,46312L,46313L,46314L,46315L,46316L,46317L,
93649 46318L,46319L,46320L,46321L,46322L,46323L,46324L,46325L,46326L,46327L,
93650 46328L,46329L,46330L,46331L,46332L,46333L,46334L,46335L,46336L,46337L,
93651 46338L,46339L,46340L,46341L,46342L,46343L,46344L,46345L,46346L,46347L,
93652 46348L,46349L,46350L,46351L,46352L,46353L,46354L,46355L,46356L,46357L,
93653 46358L,46359L,46360L,46361L,46362L,46363L,46364L,46365L,46366L,46367L,
93654 46368L,46369L,46370L,46371L,46372L,46373L,46374L,46375L,46376L,46377L,
93655 46378L,46379L,46380L,46381L,46382L,46383L,46384L,46385L,46386L,46387L,
93656 46388L,46389L,46390L,46391L,46392L,46393L,46394L,46395L,46396L,46397L,
93657 46398L,46399L,46400L,46401L,46402L,46403L,46404L,46405L,46406L,46407L,
93658 46408L,46409L,46410L,46411L,46412L,46413L,46414L,46415L,46416L,46417L,
93659 46418L,46419L,46420L,46421L,46422L,46423L,46424L,46425L,46426L,46427L,
93660 46428L,46429L,46430L,46431L,46432L,46433L,46434L,46435L,46436L,46437L,
93661 46438L,46439L,46440L,46441L,46442L,46443L,46444L,46445L,46446L,46447L,
93662 46448L,46449L,46450L,46451L,46452L,46453L,46454L,46455L,46456L,46457L,
93663 46458L,46459L,46460L,46461L,46462L,46463L,46464L,46465L,46466L,46467L,
93664 46468L,46469L,46470L,46471L,46472L,46473L,46474L,46475L,46476L,46477L,
93665 46478L,46479L,46480L,46481L,46482L,46483L,46484L,46485L,46486L,46487L,
93666 46488L,46489L,46490L,46491L,46492L,46493L,46494L,46495L,46496L,46497L,
93667 46498L,46499L,46500L,46501L,46502L,46503L,46504L,46505L,46506L,46507L,
93668 46508L,46509L,46510L,46511L,46512L,46513L,46514L,46515L,46516L,46517L,
93669 46518L,46519L,46520L,46521L,46522L,46523L,46524L,46525L,46526L,46527L,
93670 46528L,46529L,46530L,46531L,46532L,46533L,46534L,46535L,46536L,46537L,
93671 46538L,46539L,46540L,46541L,46542L,46543L,46544L,46545L,46546L,46547L,
93672 46548L,46549L,46550L,46551L,46552L,46553L,46554L,46555L,46556L,46557L,
93673 46558L,46559L,46560L,46561L,46562L,46563L,46564L,46565L,46566L,46567L,
93674 46568L,46569L,46570L,46571L,46572L,46573L,46574L,46575L,46576L,46577L,
93675 46578L,46579L,46580L,46581L,46582L,46583L,46584L,46585L,46586L,46587L,
93676 46588L,46589L,46590L,46591L,46592L,46593L,46594L,46595L,46596L,46597L,
93677 46598L,46599L,46600L,46601L,46602L,46603L,46604L,46605L,46606L,46607L,
93678 46608L,46609L,46610L,46611L,46612L,46613L,46614L,46615L,46616L,46617L,
93679 46618L,46619L,46620L,46621L,46622L,46623L,46624L,46625L,46626L,46627L,
93680 46628L,46629L,46630L,46631L,46632L,46633L,46634L,46635L,46636L,46637L,
93681 46638L,46639L,46640L,46641L,46642L,46643L,46644L,46645L,46646L,46647L,
93682 46648L,46649L,46650L,46651L,46652L,46653L,46654L,46655L,46656L,46657L,
93683 46658L,46659L,46660L,46661L,46662L,46663L,46664L,46665L,46666L,46667L,
93684 46668L,46669L,46670L,46671L,46672L,46673L,46674L,46675L,46676L,46677L,
93685 46678L,46679L,46680L,46681L,46682L,46683L,46684L,46685L,46686L,46687L,
93686 46688L,46689L,46690L,46691L,46692L,46693L,46694L,46695L,46696L,46697L,
93687 46698L,46699L,46700L,46701L,46702L,46703L,46704L,46705L,46706L,46707L,
93688 46708L,46709L,46710L,46711L,46712L,46713L,46714L,46715L,46716L,46717L,
93689 46718L,46719L,46720L,46721L,46722L,46723L,46724L,46725L,46726L,46727L,
93690 46728L,46729L,46730L,46731L,46732L,46733L,46734L,46735L,46736L,46737L,
93691 46738L,46739L,46740L,46741L,46742L,46743L,46744L,46745L,46746L,46747L,
93692 46748L,46749L,46750L,46751L,46752L,46753L,46754L,46755L,46756L,46757L,
93693 46758L,46759L,46760L,46761L,46762L,46763L,46764L,46765L,46766L,46767L,
93694 46768L,46769L,46770L,46771L,46772L,46773L,46774L,46775L,46776L,46777L,
93695 46778L,46779L,46780L,46781L,46782L,46783L,46784L,46785L,46786L,46787L,
93696 46788L,46789L,46790L,46791L,46792L,46793L,46794L,46795L,46796L,46797L,
93697 46798L,46799L,46800L,46801L,46802L,46803L,46804L,46805L,46806L,46807L,
93698 46808L,46809L,46810L,46811L,46812L,46813L,46814L,46815L,46816L,46817L,
93699 46818L,46819L,46820L,46821L,46822L,46823L,46824L,46825L,46826L,46827L,
93700 46828L,46829L,46830L,46831L,46832L,46833L,46834L,46835L,46836L,46837L,
93701 46838L,46839L,46840L,46841L,46842L,46843L,46844L,46845L,46846L,46847L,
93702 46848L,46849L,46850L,46851L,46852L,46853L,46854L,46855L,46856L,46857L,
93703 46858L,46859L,46860L,46861L,46862L,46863L,46864L,46865L,46866L,46867L,
93704 46868L,46869L,46870L,46871L,46872L,46873L,46874L,46875L,46876L,46877L,
93705 46878L,46879L,46880L,46881L,46882L,46883L,46884L,46885L,46886L,46887L,
93706 46888L,46889L,46890L,46891L,46892L,46893L,46894L,46895L,46896L,46897L,
93707 46898L,46899L,46900L,46901L,46902L,46903L,46904L,46905L,46906L,46907L,
93708 46908L,46909L,46910L,46911L,46912L,46913L,46914L,46915L,46916L,46917L,
93709 46918L,46919L,46920L,46921L,46922L,46923L,46924L,46925L,46926L,46927L,
93710 46928L,46929L,46930L,46931L,46932L,46933L,46934L,46935L,46936L,46937L,
93711 46938L,46939L,46940L,46941L,46942L,46943L,46944L,46945L,46946L,46947L,
93712 46948L,46949L,46950L,46951L,46952L,46953L,46954L,46955L,46956L,46957L,
93713 46958L,46959L,46960L,46961L,46962L,46963L,46964L,46965L,46966L,46967L,
93714 46968L,46969L,46970L,46971L,46972L,46973L,46974L,46975L,46976L,46977L,
93715 46978L,46979L,46980L,46981L,46982L,46983L,46984L,46985L,46986L,46987L,
93716 46988L,46989L,46990L,46991L,46992L,46993L,46994L,46995L,46996L,46997L,
93717 46998L,46999L,47000L,47001L,47002L,47003L,47004L,47005L,47006L,47007L,
93718 47008L,47009L,47010L,47011L,47012L,47013L,47014L,47015L,47016L,47017L,
93719 47018L,47019L,47020L,47021L,47022L,47023L,47024L,47025L,47026L,47027L,
93720 47028L,47029L,47030L,47031L,47032L,47033L,47034L,47035L,47036L,47037L,
93721 47038L,47039L,47040L,47041L,47042L,47043L,47044L,47045L,47046L,47047L,
93722 47048L,47049L,47050L,47051L,47052L,47053L,47054L,47055L,47056L,47057L,
93723 47058L,47059L,47060L,47061L,47062L,47063L,47064L,47065L,47066L,47067L,
93724 47068L,47069L,47070L,47071L,47072L,47073L,47074L,47075L,47076L,47077L,
93725 47078L,47079L,47080L,47081L,47082L,47083L,47084L,47085L,47086L,47087L,
93726 47088L,47089L,47090L,47091L,47092L,47093L,47094L,47095L,47096L,47097L,
93727 47098L,47099L,47100L,47101L,47102L,47103L,47104L,47105L,47106L,47107L,
93728 47108L,47109L,47110L,47111L,47112L,47113L,47114L,47115L,47116L,47117L,
93729 47118L,47119L,47120L,47121L,47122L,47123L,47124L,47125L,47126L,47127L,
93730 47128L,47129L,47130L,47131L,47132L,47133L,47134L,47135L,47136L,47137L,
93731 47138L,47139L,47140L,47141L,47142L,47143L,47144L,47145L,47146L,47147L,
93732 47148L,47149L,47150L,47151L,47152L,47153L,47154L,47155L,47156L,47157L,
93733 47158L,47159L,47160L,47161L,47162L,47163L,47164L,47165L,47166L,47167L,
93734 47168L,47169L,47170L,47171L,47172L,47173L,47174L,47175L,47176L,47177L,
93735 47178L,47179L,47180L,47181L,47182L,47183L,47184L,47185L,47186L,47187L,
93736 47188L,47189L,47190L,47191L,47192L,47193L,47194L,47195L,47196L,47197L,
93737 47198L,47199L,47200L,47201L,47202L,47203L,47204L,47205L,47206L,47207L,
93738 47208L,47209L,47210L,47211L,47212L,47213L,47214L,47215L,47216L,47217L,
93739 47218L,47219L,47220L,47221L,47222L,47223L,47224L,47225L,47226L,47227L,
93740 47228L,47229L,47230L,47231L,47232L,47233L,47234L,47235L,47236L,47237L,
93741 47238L,47239L,47240L,47241L,47242L,47243L,47244L,47245L,47246L,47247L,
93742 47248L,47249L,47250L,47251L,47252L,47253L,47254L,47255L,47256L,47257L,
93743 47258L,47259L,47260L,47261L,47262L,47263L,47264L,47265L,47266L,47267L,
93744 47268L,47269L,47270L,47271L,47272L,47273L,47274L,47275L,47276L,47277L,
93745 47278L,47279L,47280L,47281L,47282L,47283L,47284L,47285L,47286L,47287L,
93746 47288L,47289L,47290L,47291L,47292L,47293L,47294L,47295L,47296L,47297L,
93747 47298L,47299L,47300L,47301L,47302L,47303L,47304L,47305L,47306L,47307L,
93748 47308L,47309L,47310L,47311L,47312L,47313L,47314L,47315L,47316L,47317L,
93749 47318L,47319L,47320L,47321L,47322L,47323L,47324L,47325L,47326L,47327L,
93750 47328L,47329L,47330L,47331L,47332L,47333L,47334L,47335L,47336L,47337L,
93751 47338L,47339L,47340L,47341L,47342L,47343L,47344L,47345L,47346L,47347L,
93752 47348L,47349L,47350L,47351L,47352L,47353L,47354L,47355L,47356L,47357L,
93753 47358L,47359L,47360L,47361L,47362L,47363L,47364L,47365L,47366L,47367L,
93754 47368L,47369L,47370L,47371L,47372L,47373L,47374L,47375L,47376L,47377L,
93755 47378L,47379L,47380L,47381L,47382L,47383L,47384L,47385L,47386L,47387L,
93756 47388L,47389L,47390L,47391L,47392L,47393L,47394L,47395L,47396L,47397L,
93757 47398L,47399L,47400L,47401L,47402L,47403L,47404L,47405L,47406L,47407L,
93758 47408L,47409L,47410L,47411L,47412L,47413L,47414L,47415L,47416L,47417L,
93759 47418L,47419L,47420L,47421L,47422L,47423L,47424L,47425L,47426L,47427L,
93760 47428L,47429L,47430L,47431L,47432L,47433L,47434L,47435L,47436L,47437L,
93761 47438L,47439L,47440L,47441L,47442L,47443L,47444L,47445L,47446L,47447L,
93762 47448L,47449L,47450L,47451L,47452L,47453L,47454L,47455L,47456L,47457L,
93763 47458L,47459L,47460L,47461L,47462L,47463L,47464L,47465L,47466L,47467L,
93764 47468L,47469L,47470L,47471L,47472L,47473L,47474L,47475L,47476L,47477L,
93765 47478L,47479L,47480L,47481L,47482L,47483L,47484L,47485L,47486L,47487L,
93766 47488L,47489L,47490L,47491L,47492L,47493L,47494L,47495L,47496L,47497L,
93767 47498L,47499L,47500L,47501L,47502L,47503L,47504L,47505L,47506L,47507L,
93768 47508L,47509L,47510L,47511L,47512L,47513L,47514L,47515L,47516L,47517L,
93769 47518L,47519L,47520L,47521L,47522L,47523L,47524L,47525L,47526L,47527L,
93770 47528L,47529L,47530L,47531L,47532L,47533L,47534L,47535L,47536L,47537L,
93771 47538L,47539L,47540L,47541L,47542L,47543L,47544L,47545L,47546L,47547L,
93772 47548L,47549L,47550L,47551L,47552L,47553L,47554L,47555L,47556L,47557L,
93773 47558L,47559L,47560L,47561L,47562L,47563L,47564L,47565L,47566L,47567L,
93774 47568L,47569L,47570L,47571L,47572L,47573L,47574L,47575L,47576L,47577L,
93775 47578L,47579L,47580L,47581L,47582L,47583L,47584L,47585L,47586L,47587L,
93776 47588L,47589L,47590L,47591L,47592L,47593L,47594L,47595L,47596L,47597L,
93777 47598L,47599L,47600L,47601L,47602L,47603L,47604L,47605L,47606L,47607L,
93778 47608L,47609L,47610L,47611L,47612L,47613L,47614L,47615L,47616L,47617L,
93779 47618L,47619L,47620L,47621L,47622L,47623L,47624L,47625L,47626L,47627L,
93780 47628L,47629L,47630L,47631L,47632L,47633L,47634L,47635L,47636L,47637L,
93781 47638L,47639L,47640L,47641L,47642L,47643L,47644L,47645L,47646L,47647L,
93782 47648L,47649L,47650L,47651L,47652L,47653L,47654L,47655L,47656L,47657L,
93783 47658L,47659L,47660L,47661L,47662L,47663L,47664L,47665L,47666L,47667L,
93784 47668L,47669L,47670L,47671L,47672L,47673L,47674L,47675L,47676L,47677L,
93785 47678L,47679L,47680L,47681L,47682L,47683L,47684L,47685L,47686L,47687L,
93786 47688L,47689L,47690L,47691L,47692L,47693L,47694L,47695L,47696L,47697L,
93787 47698L,47699L,47700L,47701L,47702L,47703L,47704L,47705L,47706L,47707L,
93788 47708L,47709L,47710L,47711L,47712L,47713L,47714L,47715L,47716L,47717L,
93789 47718L,47719L,47720L,47721L,47722L,47723L,47724L,47725L,47726L,47727L,
93790 47728L,47729L,47730L,47731L,47732L,47733L,47734L,47735L,47736L,47737L,
93791 47738L,47739L,47740L,47741L,47742L,47743L,47744L,47745L,47746L,47747L,
93792 47748L,47749L,47750L,47751L,47752L,47753L,47754L,47755L,47756L,47757L,
93793 47758L,47759L,47760L,47761L,47762L,47763L,47764L,47765L,47766L,47767L,
93794 47768L,47769L,47770L,47771L,47772L,47773L,47774L,47775L,47776L,47777L,
93795 47778L,47779L,47780L,47781L,47782L,47783L,47784L,47785L,47786L,47787L,
93796 47788L,47789L,47790L,47791L,47792L,47793L,47794L,47795L,47796L,47797L,
93797 47798L,47799L,47800L,47801L,47802L,47803L,47804L,47805L,47806L,47807L,
93798 47808L,47809L,47810L,47811L,47812L,47813L,47814L,47815L,47816L,47817L,
93799 47818L,47819L,47820L,47821L,47822L,47823L,47824L,47825L,47826L,47827L,
93800 47828L,47829L,47830L,47831L,47832L,47833L,47834L,47835L,47836L,47837L,
93801 47838L,47839L,47840L,47841L,47842L,47843L,47844L,47845L,47846L,47847L,
93802 47848L,47849L,47850L,47851L,47852L,47853L,47854L,47855L,47856L,47857L,
93803 47858L,47859L,47860L,47861L,47862L,47863L,47864L,47865L,47866L,47867L,
93804 47868L,47869L,47870L,47871L,47872L,47873L,47874L,47875L,47876L,47877L,
93805 47878L,47879L,47880L,47881L,47882L,47883L,47884L,47885L,47886L,47887L,
93806 47888L,47889L,47890L,47891L,47892L,47893L,47894L,47895L,47896L,47897L,
93807 47898L,47899L,47900L,47901L,47902L,47903L,47904L,47905L,47906L,47907L,
93808 47908L,47909L,47910L,47911L,47912L,47913L,47914L,47915L,47916L,47917L,
93809 47918L,47919L,47920L,47921L,47922L,47923L,47924L,47925L,47926L,47927L,
93810 47928L,47929L,47930L,47931L,47932L,47933L,47934L,47935L,47936L,47937L,
93811 47938L,47939L,47940L,47941L,47942L,47943L,47944L,47945L,47946L,47947L,
93812 47948L,47949L,47950L,47951L,47952L,47953L,47954L,47955L,47956L,47957L,
93813 47958L,47959L,47960L,47961L,47962L,47963L,47964L,47965L,47966L,47967L,
93814 47968L,47969L,47970L,47971L,47972L,47973L,47974L,47975L,47976L,47977L,
93815 47978L,47979L,47980L,47981L,47982L,47983L,47984L,47985L,47986L,47987L,
93816 47988L,47989L,47990L,47991L,47992L,47993L,47994L,47995L,47996L,47997L,
93817 47998L,47999L,48000L,48001L,48002L,48003L,48004L,48005L,48006L,48007L,
93818 48008L,48009L,48010L,48011L,48012L,48013L,48014L,48015L,48016L,48017L,
93819 48018L,48019L,48020L,48021L,48022L,48023L,48024L,48025L,48026L,48027L,
93820 48028L,48029L,48030L,48031L,48032L,48033L,48034L,48035L,48036L,48037L,
93821 48038L,48039L,48040L,48041L,48042L,48043L,48044L,48045L,48046L,48047L,
93822 48048L,48049L,48050L,48051L,48052L,48053L,48054L,48055L,48056L,48057L,
93823 48058L,48059L,48060L,48061L,48062L,48063L,48064L,48065L,48066L,48067L,
93824 48068L,48069L,48070L,48071L,48072L,48073L,48074L,48075L,48076L,48077L,
93825 48078L,48079L,48080L,48081L,48082L,48083L,48084L,48085L,48086L,48087L,
93826 48088L,48089L,48090L,48091L,48092L,48093L,48094L,48095L,48096L,48097L,
93827 48098L,48099L,48100L,48101L,48102L,48103L,48104L,48105L,48106L,48107L,
93828 48108L,48109L,48110L,48111L,48112L,48113L,48114L,48115L,48116L,48117L,
93829 48118L,48119L,48120L,48121L,48122L,48123L,48124L,48125L,48126L,48127L,
93830 48128L,48129L,48130L,48131L,48132L,48133L,48134L,48135L,48136L,48137L,
93831 48138L,48139L,48140L,48141L,48142L,48143L,48144L,48145L,48146L,48147L,
93832 48148L,48149L,48150L,48151L,48152L,48153L,48154L,48155L,48156L,48157L,
93833 48158L,48159L,48160L,48161L,48162L,48163L,48164L,48165L,48166L,48167L,
93834 48168L,48169L,48170L,48171L,48172L,48173L,48174L,48175L,48176L,48177L,
93835 48178L,48179L,48180L,48181L,48182L,48183L,48184L,48185L,48186L,48187L,
93836 48188L,48189L,48190L,48191L,48192L,48193L,48194L,48195L,48196L,48197L,
93837 48198L,48199L,48200L,48201L,48202L,48203L,48204L,48205L,48206L,48207L,
93838 48208L,48209L,48210L,48211L,48212L,48213L,48214L,48215L,48216L,48217L,
93839 48218L,48219L,48220L,48221L,48222L,48223L,48224L,48225L,48226L,48227L,
93840 48228L,48229L,48230L,48231L,48232L,48233L,48234L,48235L,48236L,48237L,
93841 48238L,48239L,48240L,48241L,48242L,48243L,48244L,48245L,48246L,48247L,
93842 48248L,48249L,48250L,48251L,48252L,48253L,48254L,48255L,48256L,48257L,
93843 48258L,48259L,48260L,48261L,48262L,48263L,48264L,48265L,48266L,48267L,
93844 48268L,48269L,48270L,48271L,48272L,48273L,48274L,48275L,48276L,48277L,
93845 48278L,48279L,48280L,48281L,48282L,48283L,48284L,48285L,48286L,48287L,
93846 48288L,48289L,48290L,48291L,48292L,48293L,48294L,48295L,48296L,48297L,
93847 48298L,48299L,48300L,48301L,48302L,48303L,48304L,48305L,48306L,48307L,
93848 48308L,48309L,48310L,48311L,48312L,48313L,48314L,48315L,48316L,48317L,
93849 48318L,48319L,48320L,48321L,48322L,48323L,48324L,48325L,48326L,48327L,
93850 48328L,48329L,48330L,48331L,48332L,48333L,48334L,48335L,48336L,48337L,
93851 48338L,48339L,48340L,48341L,48342L,48343L,48344L,48345L,48346L,48347L,
93852 48348L,48349L,48350L,48351L,48352L,48353L,48354L,48355L,48356L,48357L,
93853 48358L,48359L,48360L,48361L,48362L,48363L,48364L,48365L,48366L,48367L,
93854 48368L,48369L,48370L,48371L,48372L,48373L,48374L,48375L,48376L,48377L,
93855 48378L,48379L,48380L,48381L,48382L,48383L,48384L,48385L,48386L,48387L,
93856 48388L,48389L,48390L,48391L,48392L,48393L,48394L,48395L,48396L,48397L,
93857 48398L,48399L,48400L,48401L,48402L,48403L,48404L,48405L,48406L,48407L,
93858 48408L,48409L,48410L,48411L,48412L,48413L,48414L,48415L,48416L,48417L,
93859 48418L,48419L,48420L,48421L,48422L,48423L,48424L,48425L,48426L,48427L,
93860 48428L,48429L,48430L,48431L,48432L,48433L,48434L,48435L,48436L,48437L,
93861 48438L,48439L,48440L,48441L,48442L,48443L,48444L,48445L,48446L,48447L,
93862 48448L,48449L,48450L,48451L,48452L,48453L,48454L,48455L,48456L,48457L,
93863 48458L,48459L,48460L,48461L,48462L,48463L,48464L,48465L,48466L,48467L,
93864 48468L,48469L,48470L,48471L,48472L,48473L,48474L,48475L,48476L,48477L,
93865 48478L,48479L,48480L,48481L,48482L,48483L,48484L,48485L,48486L,48487L,
93866 48488L,48489L,48490L,48491L,48492L,48493L,48494L,48495L,48496L,48497L,
93867 48498L,48499L,48500L,48501L,48502L,48503L,48504L,48505L,48506L,48507L,
93868 48508L,48509L,48510L,48511L,48512L,48513L,48514L,48515L,48516L,48517L,
93869 48518L,48519L,48520L,48521L,48522L,48523L,48524L,48525L,48526L,48527L,
93870 48528L,48529L,48530L,48531L,48532L,48533L,48534L,48535L,48536L,48537L,
93871 48538L,48539L,48540L,48541L,48542L,48543L,48544L,48545L,48546L,48547L,
93872 48548L,48549L,48550L,48551L,48552L,48553L,48554L,48555L,48556L,48557L,
93873 48558L,48559L,48560L,48561L,48562L,48563L,48564L,48565L,48566L,48567L,
93874 48568L,48569L,48570L,48571L,48572L,48573L,48574L,48575L,48576L,48577L,
93875 48578L,48579L,48580L,48581L,48582L,48583L,48584L,48585L,48586L,48587L,
93876 48588L,48589L,48590L,48591L,48592L,48593L,48594L,48595L,48596L,48597L,
93877 48598L,48599L,48600L,48601L,48602L,48603L,48604L,48605L,48606L,48607L,
93878 48608L,48609L,48610L,48611L,48612L,48613L,48614L,48615L,48616L,48617L,
93879 48618L,48619L,48620L,48621L,48622L,48623L,48624L,48625L,48626L,48627L,
93880 48628L,48629L,48630L,48631L,48632L,48633L,48634L,48635L,48636L,48637L,
93881 48638L,48639L,48640L,48641L,48642L,48643L,48644L,48645L,48646L,48647L,
93882 48648L,48649L,48650L,48651L,48652L,48653L,48654L,48655L,48656L,48657L,
93883 48658L,48659L,48660L,48661L,48662L,48663L,48664L,48665L,48666L,48667L,
93884 48668L,48669L,48670L,48671L,48672L,48673L,48674L,48675L,48676L,48677L,
93885 48678L,48679L,48680L,48681L,48682L,48683L,48684L,48685L,48686L,48687L,
93886 48688L,48689L,48690L,48691L,48692L,48693L,48694L,48695L,48696L,48697L,
93887 48698L,48699L,48700L,48701L,48702L,48703L,48704L,48705L,48706L,48707L,
93888 48708L,48709L,48710L,48711L,48712L,48713L,48714L,48715L,48716L,48717L,
93889 48718L,48719L,48720L,48721L,48722L,48723L,48724L,48725L,48726L,48727L,
93890 48728L,48729L,48730L,48731L,48732L,48733L,48734L,48735L,48736L,48737L,
93891 48738L,48739L,48740L,48741L,48742L,48743L,48744L,48745L,48746L,48747L,
93892 48748L,48749L,48750L,48751L,48752L,48753L,48754L,48755L,48756L,48757L,
93893 48758L,48759L,48760L,48761L,48762L,48763L,48764L,48765L,48766L,48767L,
93894 48768L,48769L,48770L,48771L,48772L,48773L,48774L,48775L,48776L,48777L,
93895 48778L,48779L,48780L,48781L,48782L,48783L,48784L,48785L,48786L,48787L,
93896 48788L,48789L,48790L,48791L,48792L,48793L,48794L,48795L,48796L,48797L,
93897 48798L,48799L,48800L,48801L,48802L,48803L,48804L,48805L,48806L,48807L,
93898 48808L,48809L,48810L,48811L,48812L,48813L,48814L,48815L,48816L,48817L,
93899 48818L,48819L,48820L,48821L,48822L,48823L,48824L,48825L,48826L,48827L,
93900 48828L,48829L,48830L,48831L,48832L,48833L,48834L,48835L,48836L,48837L,
93901 48838L,48839L,48840L,48841L,48842L,48843L,48844L,48845L,48846L,48847L,
93902 48848L,48849L,48850L,48851L,48852L,48853L,48854L,48855L,48856L,48857L,
93903 48858L,48859L,48860L,48861L,48862L,48863L,48864L,48865L,48866L,48867L,
93904 48868L,48869L,48870L,48871L,48872L,48873L,48874L,48875L,48876L,48877L,
93905 48878L,48879L,48880L,48881L,48882L,48883L,48884L,48885L,48886L,48887L,
93906 48888L,48889L,48890L,48891L,48892L,48893L,48894L,48895L,48896L,48897L,
93907 48898L,48899L,48900L,48901L,48902L,48903L,48904L,48905L,48906L,48907L,
93908 48908L,48909L,48910L,48911L,48912L,48913L,48914L,48915L,48916L,48917L,
93909 48918L,48919L,48920L,48921L,48922L,48923L,48924L,48925L,48926L,48927L,
93910 48928L,48929L,48930L,48931L,48932L,48933L,48934L,48935L,48936L,48937L,
93911 48938L,48939L,48940L,48941L,48942L,48943L,48944L,48945L,48946L,48947L,
93912 48948L,48949L,48950L,48951L,48952L,48953L,48954L,48955L,48956L,48957L,
93913 48958L,48959L,48960L,48961L,48962L,48963L,48964L,48965L,48966L,48967L,
93914 48968L,48969L,48970L,48971L,48972L,48973L,48974L,48975L,48976L,48977L,
93915 48978L,48979L,48980L,48981L,48982L,48983L,48984L,48985L,48986L,48987L,
93916 48988L,48989L,48990L,48991L,48992L,48993L,48994L,48995L,48996L,48997L,
93917 48998L,48999L,49000L,49001L,49002L,49003L,49004L,49005L,49006L,49007L,
93918 49008L,49009L,49010L,49011L,49012L,49013L,49014L,49015L,49016L,49017L,
93919 49018L,49019L,49020L,49021L,49022L,49023L,49024L,49025L,49026L,49027L,
93920 49028L,49029L,49030L,49031L,49032L,49033L,49034L,49035L,49036L,49037L,
93921 49038L,49039L,49040L,49041L,49042L,49043L,49044L,49045L,49046L,49047L,
93922 49048L,49049L,49050L,49051L,49052L,49053L,49054L,49055L,49056L,49057L,
93923 49058L,49059L,49060L,49061L,49062L,49063L,49064L,49065L,49066L,49067L,
93924 49068L,49069L,49070L,49071L,49072L,49073L,49074L,49075L,49076L,49077L,
93925 49078L,49079L,49080L,49081L,49082L,49083L,49084L,49085L,49086L,49087L,
93926 49088L,49089L,49090L,49091L,49092L,49093L,49094L,49095L,49096L,49097L,
93927 49098L,49099L,49100L,49101L,49102L,49103L,49104L,49105L,49106L,49107L,
93928 49108L,49109L,49110L,49111L,49112L,49113L,49114L,49115L,49116L,49117L,
93929 49118L,49119L,49120L,49121L,49122L,49123L,49124L,49125L,49126L,49127L,
93930 49128L,49129L,49130L,49131L,49132L,49133L,49134L,49135L,49136L,49137L,
93931 49138L,49139L,49140L,49141L,49142L,49143L,49144L,49145L,49146L,49147L,
93932 49148L,49149L,49150L,49151L,49152L,49153L,49154L,49155L,49156L,49157L,
93933 49158L,49159L,49160L,49161L,49162L,49163L,49164L,49165L,49166L,49167L,
93934 49168L,49169L,49170L,49171L,49172L,49173L,49174L,49175L,49176L,49177L,
93935 49178L,49179L,49180L,49181L,49182L,49183L,49184L,49185L,49186L,49187L,
93936 49188L,49189L,49190L,49191L,49192L,49193L,49194L,49195L,49196L,49197L,
93937 49198L,49199L,49200L,49201L,49202L,49203L,49204L,49205L,49206L,49207L,
93938 49208L,49209L,49210L,49211L,49212L,49213L,49214L,49215L,49216L,49217L,
93939 49218L,49219L,49220L,49221L,49222L,49223L,49224L,49225L,49226L,49227L,
93940 49228L,49229L,49230L,49231L,49232L,49233L,49234L,49235L,49236L,49237L,
93941 49238L,49239L,49240L,49241L,49242L,49243L,49244L,49245L,49246L,49247L,
93942 49248L,49249L,49250L,49251L,49252L,49253L,49254L,49255L,49256L,49257L,
93943 49258L,49259L,49260L,49261L,49262L,49263L,49264L,49265L,49266L,49267L,
93944 49268L,49269L,49270L,49271L,49272L,49273L,49274L,49275L,49276L,49277L,
93945 49278L,49279L,49280L,49281L,49282L,49283L,49284L,49285L,49286L,49287L,
93946 49288L,49289L,49290L,49291L,49292L,49293L,49294L,49295L,49296L,49297L,
93947 49298L,49299L,49300L,49301L,49302L,49303L,49304L,49305L,49306L,49307L,
93948 49308L,49309L,49310L,49311L,49312L,49313L,49314L,49315L,49316L,49317L,
93949 49318L,49319L,49320L,49321L,49322L,49323L,49324L,49325L,49326L,49327L,
93950 49328L,49329L,49330L,49331L,49332L,49333L,49334L,49335L,49336L,49337L,
93951 49338L,49339L,49340L,49341L,49342L,49343L,49344L,49345L,49346L,49347L,
93952 49348L,49349L,49350L,49351L,49352L,49353L,49354L,49355L,49356L,49357L,
93953 49358L,49359L,49360L,49361L,49362L,49363L,49364L,49365L,49366L,49367L,
93954 49368L,49369L,49370L,49371L,49372L,49373L,49374L,49375L,49376L,49377L,
93955 49378L,49379L,49380L,49381L,49382L,49383L,49384L,49385L,49386L,49387L,
93956 49388L,49389L,49390L,49391L,49392L,49393L,49394L,49395L,49396L,49397L,
93957 49398L,49399L,49400L,49401L,49402L,49403L,49404L,49405L,49406L,49407L,
93958 49408L,49409L,49410L,49411L,49412L,49413L,49414L,49415L,49416L,49417L,
93959 49418L,49419L,49420L,49421L,49422L,49423L,49424L,49425L,49426L,49427L,
93960 49428L,49429L,49430L,49431L,49432L,49433L,49434L,49435L,49436L,49437L,
93961 49438L,49439L,49440L,49441L,49442L,49443L,49444L,49445L,49446L,49447L,
93962 49448L,49449L,49450L,49451L,49452L,49453L,49454L,49455L,49456L,49457L,
93963 49458L,49459L,49460L,49461L,49462L,49463L,49464L,49465L,49466L,49467L,
93964 49468L,49469L,49470L,49471L,49472L,49473L,49474L,49475L,49476L,49477L,
93965 49478L,49479L,49480L,49481L,49482L,49483L,49484L,49485L,49486L,49487L,
93966 49488L,49489L,49490L,49491L,49492L,49493L,49494L,49495L,49496L,49497L,
93967 49498L,49499L,49500L,49501L,49502L,49503L,49504L,49505L,49506L,49507L,
93968 49508L,49509L,49510L,49511L,49512L,49513L,49514L,49515L,49516L,49517L,
93969 49518L,49519L,49520L,49521L,49522L,49523L,49524L,49525L,49526L,49527L,
93970 49528L,49529L,49530L,49531L,49532L,49533L,49534L,49535L,49536L,49537L,
93971 49538L,49539L,49540L,49541L,49542L,49543L,49544L,49545L,49546L,49547L,
93972 49548L,49549L,49550L,49551L,49552L,49553L,49554L,49555L,49556L,49557L,
93973 49558L,49559L,49560L,49561L,49562L,49563L,49564L,49565L,49566L,49567L,
93974 49568L,49569L,49570L,49571L,49572L,49573L,49574L,49575L,49576L,49577L,
93975 49578L,49579L,49580L,49581L,49582L,49583L,49584L,49585L,49586L,49587L,
93976 49588L,49589L,49590L,49591L,49592L,49593L,49594L,49595L,49596L,49597L,
93977 49598L,49599L,49600L,49601L,49602L,49603L,49604L,49605L,49606L,49607L,
93978 49608L,49609L,49610L,49611L,49612L,49613L,49614L,49615L,49616L,49617L,
93979 49618L,49619L,49620L,49621L,49622L,49623L,49624L,49625L,49626L,49627L,
93980 49628L,49629L,49630L,49631L,49632L,49633L,49634L,49635L,49636L,49637L,
93981 49638L,49639L,49640L,49641L,49642L,49643L,49644L,49645L,49646L,49647L,
93982 49648L,49649L,49650L,49651L,49652L,49653L,49654L,49655L,49656L,49657L,
93983 49658L,49659L,49660L,49661L,49662L,49663L,49664L,49665L,49666L,49667L,
93984 49668L,49669L,49670L,49671L,49672L,49673L,49674L,49675L,49676L,49677L,
93985 49678L,49679L,49680L,49681L,49682L,49683L,49684L,49685L,49686L,49687L,
93986 49688L,49689L,49690L,49691L,49692L,49693L,49694L,49695L,49696L,49697L,
93987 49698L,49699L,49700L,49701L,49702L,49703L,49704L,49705L,49706L,49707L,
93988 49708L,49709L,49710L,49711L,49712L,49713L,49714L,49715L,49716L,49717L,
93989 49718L,49719L,49720L,49721L,49722L,49723L,49724L,49725L,49726L,49727L,
93990 49728L,49729L,49730L,49731L,49732L,49733L,49734L,49735L,49736L,49737L,
93991 49738L,49739L,49740L,49741L,49742L,49743L,49744L,49745L,49746L,49747L,
93992 49748L,49749L,49750L,49751L,49752L,49753L,49754L,49755L,49756L,49757L,
93993 49758L,49759L,49760L,49761L,49762L,49763L,49764L,49765L,49766L,49767L,
93994 49768L,49769L,49770L,49771L,49772L,49773L,49774L,49775L,49776L,49777L,
93995 49778L,49779L,49780L,49781L,49782L,49783L,49784L,49785L,49786L,49787L,
93996 49788L,49789L,49790L,49791L,49792L,49793L,49794L,49795L,49796L,49797L,
93997 49798L,49799L,49800L,49801L,49802L,49803L,49804L,49805L,49806L,49807L,
93998 49808L,49809L,49810L,49811L,49812L,49813L,49814L,49815L,49816L,49817L,
93999 49818L,49819L,49820L,49821L,49822L,49823L,49824L,49825L,49826L,49827L,
94000 49828L,49829L,49830L,49831L,49832L,49833L,49834L,49835L,49836L,49837L,
94001 49838L,49839L,49840L,49841L,49842L,49843L,49844L,49845L,49846L,49847L,
94002 49848L,49849L,49850L,49851L,49852L,49853L,49854L,49855L,49856L,49857L,
94003 49858L,49859L,49860L,49861L,49862L,49863L,49864L,49865L,49866L,49867L,
94004 49868L,49869L,49870L,49871L,49872L,49873L,49874L,49875L,49876L,49877L,
94005 49878L,49879L,49880L,49881L,49882L,49883L,49884L,49885L,49886L,49887L,
94006 49888L,49889L,49890L,49891L,49892L,49893L,49894L,49895L,49896L,49897L,
94007 49898L,49899L,49900L,49901L,49902L,49903L,49904L,49905L,49906L,49907L,
94008 49908L,49909L,49910L,49911L,49912L,49913L,49914L,49915L,49916L,49917L,
94009 49918L,49919L,49920L,49921L,49922L,49923L,49924L,49925L,49926L,49927L,
94010 49928L,49929L,49930L,49931L,49932L,49933L,49934L,49935L,49936L,49937L,
94011 49938L,49939L,49940L,49941L,49942L,49943L,49944L,49945L,49946L,49947L,
94012 49948L,49949L,49950L,49951L,49952L,49953L,49954L,49955L,49956L,49957L,
94013 49958L,49959L,49960L,49961L,49962L,49963L,49964L,49965L,49966L,49967L,
94014 49968L,49969L,49970L,49971L,49972L,49973L,49974L,49975L,49976L,49977L,
94015 49978L,49979L,49980L,49981L,49982L,49983L,49984L,49985L,49986L,49987L,
94016 49988L,49989L,49990L,49991L,49992L,49993L,49994L,49995L,49996L,49997L,
94017 49998L,49999L,50000L,50001L,50002L,50003L,50004L,50005L,50006L,50007L,
94018 50008L,50009L,50010L,50011L,50012L,50013L,50014L,50015L,50016L,50017L,
94019 50018L,50019L,50020L,50021L,50022L,50023L,50024L,50025L,50026L,50027L,
94020 50028L,50029L,50030L,50031L,50032L,50033L,50034L,50035L,50036L,50037L,
94021 50038L,50039L,50040L,50041L,50042L,50043L,50044L,50045L,50046L,50047L,
94022 50048L,50049L,50050L,50051L,50052L,50053L,50054L,50055L,50056L,50057L,
94023 50058L,50059L,50060L,50061L,50062L,50063L,50064L,50065L,50066L,50067L,
94024 50068L,50069L,50070L,50071L,50072L,50073L,50074L,50075L,50076L,50077L,
94025 50078L,50079L,50080L,50081L,50082L,50083L,50084L,50085L,50086L,50087L,
94026 50088L,50089L,50090L,50091L,50092L,50093L,50094L,50095L,50096L,50097L,
94027 50098L,50099L,50100L,50101L,50102L,50103L,50104L,50105L,50106L,50107L,
94028 50108L,50109L,50110L,50111L,50112L,50113L,50114L,50115L,50116L,50117L,
94029 50118L,50119L,50120L,50121L,50122L,50123L,50124L,50125L,50126L,50127L,
94030 50128L,50129L,50130L,50131L,50132L,50133L,50134L,50135L,50136L,50137L,
94031 50138L,50139L,50140L,50141L,50142L,50143L,50144L,50145L,50146L,50147L,
94032 50148L,50149L,50150L,50151L,50152L,50153L,50154L,50155L,50156L,50157L,
94033 50158L,50159L,50160L,50161L,50162L,50163L,50164L,50165L,50166L,50167L,
94034 50168L,50169L,50170L,50171L,50172L,50173L,50174L,50175L,50176L,50177L,
94035 50178L,50179L,50180L,50181L,50182L,50183L,50184L,50185L,50186L,50187L,
94036 50188L,50189L,50190L,50191L,50192L,50193L,50194L,50195L,50196L,50197L,
94037 50198L,50199L,50200L,50201L,50202L,50203L,50204L,50205L,50206L,50207L,
94038 50208L,50209L,50210L,50211L,50212L,50213L,50214L,50215L,50216L,50217L,
94039 50218L,50219L,50220L,50221L,50222L,50223L,50224L,50225L,50226L,50227L,
94040 50228L,50229L,50230L,50231L,50232L,50233L,50234L,50235L,50236L,50237L,
94041 50238L,50239L,50240L,50241L,50242L,50243L,50244L,50245L,50246L,50247L,
94042 50248L,50249L,50250L,50251L,50252L,50253L,50254L,50255L,50256L,50257L,
94043 50258L,50259L,50260L,50261L,50262L,50263L,50264L,50265L,50266L,50267L,
94044 50268L,50269L,50270L,50271L,50272L,50273L,50274L,50275L,50276L,50277L,
94045 50278L,50279L,50280L,50281L,50282L,50283L,50284L,50285L,50286L,50287L,
94046 50288L,50289L,50290L,50291L,50292L,50293L,50294L,50295L,50296L,50297L,
94047 50298L,50299L,50300L,50301L,50302L,50303L,50304L,50305L,50306L,50307L,
94048 50308L,50309L,50310L,50311L,50312L,50313L,50314L,50315L,50316L,50317L,
94049 50318L,50319L,50320L,50321L,50322L,50323L,50324L,50325L,50326L,50327L,
94050 50328L,50329L,50330L,50331L,50332L,50333L,50334L,50335L,50336L,50337L,
94051 50338L,50339L,50340L,50341L,50342L,50343L,50344L,50345L,50346L,50347L,
94052 50348L,50349L,50350L,50351L,50352L,50353L,50354L,50355L,50356L,50357L,
94053 50358L,50359L,50360L,50361L,50362L,50363L,50364L,50365L,50366L,50367L,
94054 50368L,50369L,50370L,50371L,50372L,50373L,50374L,50375L,50376L,50377L,
94055 50378L,50379L,50380L,50381L,50382L,50383L,50384L,50385L,50386L,50387L,
94056 50388L,50389L,50390L,50391L,50392L,50393L,50394L,50395L,50396L,50397L,
94057 50398L,50399L,50400L,50401L,50402L,50403L,50404L,50405L,50406L,50407L,
94058 50408L,50409L,50410L,50411L,50412L,50413L,50414L,50415L,50416L,50417L,
94059 50418L,50419L,50420L,50421L,50422L,50423L,50424L,50425L,50426L,50427L,
94060 50428L,50429L,50430L,50431L,50432L,50433L,50434L,50435L,50436L,50437L,
94061 50438L,50439L,50440L,50441L,50442L,50443L,50444L,50445L,50446L,50447L,
94062 50448L,50449L,50450L,50451L,50452L,50453L,50454L,50455L,50456L,50457L,
94063 50458L,50459L,50460L,50461L,50462L,50463L,50464L,50465L,50466L,50467L,
94064 50468L,50469L,50470L,50471L,50472L,50473L,50474L,50475L,50476L,50477L,
94065 50478L,50479L,50480L,50481L,50482L,50483L,50484L,50485L,50486L,50487L,
94066 50488L,50489L,50490L,50491L,50492L,50493L,50494L,50495L,50496L,50497L,
94067 50498L,50499L,50500L,50501L,50502L,50503L,50504L,50505L,50506L,50507L,
94068 50508L,50509L,50510L,50511L,50512L,50513L,50514L,50515L,50516L,50517L,
94069 50518L,50519L,50520L,50521L,50522L,50523L,50524L,50525L,50526L,50527L,
94070 50528L,50529L,50530L,50531L,50532L,50533L,50534L,50535L,50536L,50537L,
94071 50538L,50539L,50540L,50541L,50542L,50543L,50544L,50545L,50546L,50547L,
94072 50548L,50549L,50550L,50551L,50552L,50553L,50554L,50555L,50556L,50557L,
94073 50558L,50559L,50560L,50561L,50562L,50563L,50564L,50565L,50566L,50567L,
94074 50568L,50569L,50570L,50571L,50572L,50573L,50574L,50575L,50576L,50577L,
94075 50578L,50579L,50580L,50581L,50582L,50583L,50584L,50585L,50586L,50587L,
94076 50588L,50589L,50590L,50591L,50592L,50593L,50594L,50595L,50596L,50597L,
94077 50598L,50599L,50600L,50601L,50602L,50603L,50604L,50605L,50606L,50607L,
94078 50608L,50609L,50610L,50611L,50612L,50613L,50614L,50615L,50616L,50617L,
94079 50618L,50619L,50620L,50621L,50622L,50623L,50624L,50625L,50626L,50627L,
94080 50628L,50629L,50630L,50631L,50632L,50633L,50634L,50635L,50636L,50637L,
94081 50638L,50639L,50640L,50641L,50642L,50643L,50644L,50645L,50646L,50647L,
94082 50648L,50649L,50650L,50651L,50652L,50653L,50654L,50655L,50656L,50657L,
94083 50658L,50659L,50660L,50661L,50662L,50663L,50664L,50665L,50666L,50667L,
94084 50668L,50669L,50670L,50671L,50672L,50673L,50674L,50675L,50676L,50677L,
94085 50678L,50679L,50680L,50681L,50682L,50683L,50684L,50685L,50686L,50687L,
94086 50688L,50689L,50690L,50691L,50692L,50693L,50694L,50695L,50696L,50697L,
94087 50698L,50699L,50700L,50701L,50702L,50703L,50704L,50705L,50706L,50707L,
94088 50708L,50709L,50710L,50711L,50712L,50713L,50714L,50715L,50716L,50717L,
94089 50718L,50719L,50720L,50721L,50722L,50723L,50724L,50725L,50726L,50727L,
94090 50728L,50729L,50730L,50731L,50732L,50733L,50734L,50735L,50736L,50737L,
94091 50738L,50739L,50740L,50741L,50742L,50743L,50744L,50745L,50746L,50747L,
94092 50748L,50749L,50750L,50751L,50752L,50753L,50754L,50755L,50756L,50757L,
94093 50758L,50759L,50760L,50761L,50762L,50763L,50764L,50765L,50766L,50767L,
94094 50768L,50769L,50770L,50771L,50772L,50773L,50774L,50775L,50776L,50777L,
94095 50778L,50779L,50780L,50781L,50782L,50783L,50784L,50785L,50786L,50787L,
94096 50788L,50789L,50790L,50791L,50792L,50793L,50794L,50795L,50796L,50797L,
94097 50798L,50799L,50800L,50801L,50802L,50803L,50804L,50805L,50806L,50807L,
94098 50808L,50809L,50810L,50811L,50812L,50813L,50814L,50815L,50816L,50817L,
94099 50818L,50819L,50820L,50821L,50822L,50823L,50824L,50825L,50826L,50827L,
94100 50828L,50829L,50830L,50831L,50832L,50833L,50834L,50835L,50836L,50837L,
94101 50838L,50839L,50840L,50841L,50842L,50843L,50844L,50845L,50846L,50847L,
94102 50848L,50849L,50850L,50851L,50852L,50853L,50854L,50855L,50856L,50857L,
94103 50858L,50859L,50860L,50861L,50862L,50863L,50864L,50865L,50866L,50867L,
94104 50868L,50869L,50870L,50871L,50872L,50873L,50874L,50875L,50876L,50877L,
94105 50878L,50879L,50880L,50881L,50882L,50883L,50884L,50885L,50886L,50887L,
94106 50888L,50889L,50890L,50891L,50892L,50893L,50894L,50895L,50896L,50897L,
94107 50898L,50899L,50900L,50901L,50902L,50903L,50904L,50905L,50906L,50907L,
94108 50908L,50909L,50910L,50911L,50912L,50913L,50914L,50915L,50916L,50917L,
94109 50918L,50919L,50920L,50921L,50922L,50923L,50924L,50925L,50926L,50927L,
94110 50928L,50929L,50930L,50931L,50932L,50933L,50934L,50935L,50936L,50937L,
94111 50938L,50939L,50940L,50941L,50942L,50943L,50944L,50945L,50946L,50947L,
94112 50948L,50949L,50950L,50951L,50952L,50953L,50954L,50955L,50956L,50957L,
94113 50958L,50959L,50960L,50961L,50962L,50963L,50964L,50965L,50966L,50967L,
94114 50968L,50969L,50970L,50971L,50972L,50973L,50974L,50975L,50976L,50977L,
94115 50978L,50979L,50980L,50981L,50982L,50983L,50984L,50985L,50986L,50987L,
94116 50988L,50989L,50990L,50991L,50992L,50993L,50994L,50995L,50996L,50997L,
94117 50998L,50999L,51000L,51001L,51002L,51003L,51004L,51005L,51006L,51007L,
94118 51008L,51009L,51010L,51011L,51012L,51013L,51014L,51015L,51016L,51017L,
94119 51018L,51019L,51020L,51021L,51022L,51023L,51024L,51025L,51026L,51027L,
94120 51028L,51029L,51030L,51031L,51032L,51033L,51034L,51035L,51036L,51037L,
94121 51038L,51039L,51040L,51041L,51042L,51043L,51044L,51045L,51046L,51047L,
94122 51048L,51049L,51050L,51051L,51052L,51053L,51054L,51055L,51056L,51057L,
94123 51058L,51059L,51060L,51061L,51062L,51063L,51064L,51065L,51066L,51067L,
94124 51068L,51069L,51070L,51071L,51072L,51073L,51074L,51075L,51076L,51077L,
94125 51078L,51079L,51080L,51081L,51082L,51083L,51084L,51085L,51086L,51087L,
94126 51088L,51089L,51090L,51091L,51092L,51093L,51094L,51095L,51096L,51097L,
94127 51098L,51099L,51100L,51101L,51102L,51103L,51104L,51105L,51106L,51107L,
94128 51108L,51109L,51110L,51111L,51112L,51113L,51114L,51115L,51116L,51117L,
94129 51118L,51119L,51120L,51121L,51122L,51123L,51124L,51125L,51126L,51127L,
94130 51128L,51129L,51130L,51131L,51132L,51133L,51134L,51135L,51136L,51137L,
94131 51138L,51139L,51140L,51141L,51142L,51143L,51144L,51145L,51146L,51147L,
94132 51148L,51149L,51150L,51151L,51152L,51153L,51154L,51155L,51156L,51157L,
94133 51158L,51159L,51160L,51161L,51162L,51163L,51164L,51165L,51166L,51167L,
94134 51168L,51169L,51170L,51171L,51172L,51173L,51174L,51175L,51176L,51177L,
94135 51178L,51179L,51180L,51181L,51182L,51183L,51184L,51185L,51186L,51187L,
94136 51188L,51189L,51190L,51191L,51192L,51193L,51194L,51195L,51196L,51197L,
94137 51198L,51199L,51200L,51201L,51202L,51203L,51204L,51205L,51206L,51207L,
94138 51208L,51209L,51210L,51211L,51212L,51213L,51214L,51215L,51216L,51217L,
94139 51218L,51219L,51220L,51221L,51222L,51223L,51224L,51225L,51226L,51227L,
94140 51228L,51229L,51230L,51231L,51232L,51233L,51234L,51235L,51236L,51237L,
94141 51238L,51239L,51240L,51241L,51242L,51243L,51244L,51245L,51246L,51247L,
94142 51248L,51249L,51250L,51251L,51252L,51253L,51254L,51255L,51256L,51257L,
94143 51258L,51259L,51260L,51261L,51262L,51263L,51264L,51265L,51266L,51267L,
94144 51268L,51269L,51270L,51271L,51272L,51273L,51274L,51275L,51276L,51277L,
94145 51278L,51279L,51280L,51281L,51282L,51283L,51284L,51285L,51286L,51287L,
94146 51288L,51289L,51290L,51291L,51292L,51293L,51294L,51295L,51296L,51297L,
94147 51298L,51299L,51300L,51301L,51302L,51303L,51304L,51305L,51306L,51307L,
94148 51308L,51309L,51310L,51311L,51312L,51313L,51314L,51315L,51316L,51317L,
94149 51318L,51319L,51320L,51321L,51322L,51323L,51324L,51325L,51326L,51327L,
94150 51328L,51329L,51330L,51331L,51332L,51333L,51334L,51335L,51336L,51337L,
94151 51338L,51339L,51340L,51341L,51342L,51343L,51344L,51345L,51346L,51347L,
94152 51348L,51349L,51350L,51351L,51352L,51353L,51354L,51355L,51356L,51357L,
94153 51358L,51359L,51360L,51361L,51362L,51363L,51364L,51365L,51366L,51367L,
94154 51368L,51369L,51370L,51371L,51372L,51373L,51374L,51375L,51376L,51377L,
94155 51378L,51379L,51380L,51381L,51382L,51383L,51384L,51385L,51386L,51387L,
94156 51388L,51389L,51390L,51391L,51392L,51393L,51394L,51395L,51396L,51397L,
94157 51398L,51399L,51400L,51401L,51402L,51403L,51404L,51405L,51406L,51407L,
94158 51408L,51409L,51410L,51411L,51412L,51413L,51414L,51415L,51416L,51417L,
94159 51418L,51419L,51420L,51421L,51422L,51423L,51424L,51425L,51426L,51427L,
94160 51428L,51429L,51430L,51431L,51432L,51433L,51434L,51435L,51436L,51437L,
94161 51438L,51439L,51440L,51441L,51442L,51443L,51444L,51445L,51446L,51447L,
94162 51448L,51449L,51450L,51451L,51452L,51453L,51454L,51455L,51456L,51457L,
94163 51458L,51459L,51460L,51461L,51462L,51463L,51464L,51465L,51466L,51467L,
94164 51468L,51469L,51470L,51471L,51472L,51473L,51474L,51475L,51476L,51477L,
94165 51478L,51479L,51480L,51481L,51482L,51483L,51484L,51485L,51486L,51487L,
94166 51488L,51489L,51490L,51491L,51492L,51493L,51494L,51495L,51496L,51497L,
94167 51498L,51499L,51500L,51501L,51502L,51503L,51504L,51505L,51506L,51507L,
94168 51508L,51509L,51510L,51511L,51512L,51513L,51514L,51515L,51516L,51517L,
94169 51518L,51519L,51520L,51521L,51522L,51523L,51524L,51525L,51526L,51527L,
94170 51528L,51529L,51530L,51531L,51532L,51533L,51534L,51535L,51536L,51537L,
94171 51538L,51539L,51540L,51541L,51542L,51543L,51544L,51545L,51546L,51547L,
94172 51548L,51549L,51550L,51551L,51552L,51553L,51554L,51555L,51556L,51557L,
94173 51558L,51559L,51560L,51561L,51562L,51563L,51564L,51565L,51566L,51567L,
94174 51568L,51569L,51570L,51571L,51572L,51573L,51574L,51575L,51576L,51577L,
94175 51578L,51579L,51580L,51581L,51582L,51583L,51584L,51585L,51586L,51587L,
94176 51588L,51589L,51590L,51591L,51592L,51593L,51594L,51595L,51596L,51597L,
94177 51598L,51599L,51600L,51601L,51602L,51603L,51604L,51605L,51606L,51607L,
94178 51608L,51609L,51610L,51611L,51612L,51613L,51614L,51615L,51616L,51617L,
94179 51618L,51619L,51620L,51621L,51622L,51623L,51624L,51625L,51626L,51627L,
94180 51628L,51629L,51630L,51631L,51632L,51633L,51634L,51635L,51636L,51637L,
94181 51638L,51639L,51640L,51641L,51642L,51643L,51644L,51645L,51646L,51647L,
94182 51648L,51649L,51650L,51651L,51652L,51653L,51654L,51655L,51656L,51657L,
94183 51658L,51659L,51660L,51661L,51662L,51663L,51664L,51665L,51666L,51667L,
94184 51668L,51669L,51670L,51671L,51672L,51673L,51674L,51675L,51676L,51677L,
94185 51678L,51679L,51680L,51681L,51682L,51683L,51684L,51685L,51686L,51687L,
94186 51688L,51689L,51690L,51691L,51692L,51693L,51694L,51695L,51696L,51697L,
94187 51698L,51699L,51700L,51701L,51702L,51703L,51704L,51705L,51706L,51707L,
94188 51708L,51709L,51710L,51711L,51712L,51713L,51714L,51715L,51716L,51717L,
94189 51718L,51719L,51720L,51721L,51722L,51723L,51724L,51725L,51726L,51727L,
94190 51728L,51729L,51730L,51731L,51732L,51733L,51734L,51735L,51736L,51737L,
94191 51738L,51739L,51740L,51741L,51742L,51743L,51744L,51745L,51746L,51747L,
94192 51748L,51749L,51750L,51751L,51752L,51753L,51754L,51755L,51756L,51757L,
94193 51758L,51759L,51760L,51761L,51762L,51763L,51764L,51765L,51766L,51767L,
94194 51768L,51769L,51770L,51771L,51772L,51773L,51774L,51775L,51776L,51777L,
94195 51778L,51779L,51780L,51781L,51782L,51783L,51784L,51785L,51786L,51787L,
94196 51788L,51789L,51790L,51791L,51792L,51793L,51794L,51795L,51796L,51797L,
94197 51798L,51799L,51800L,51801L,51802L,51803L,51804L,51805L,51806L,51807L,
94198 51808L,51809L,51810L,51811L,51812L,51813L,51814L,51815L,51816L,51817L,
94199 51818L,51819L,51820L,51821L,51822L,51823L,51824L,51825L,51826L,51827L,
94200 51828L,51829L,51830L,51831L,51832L,51833L,51834L,51835L,51836L,51837L,
94201 51838L,51839L,51840L,51841L,51842L,51843L,51844L,51845L,51846L,51847L,
94202 51848L,51849L,51850L,51851L,51852L,51853L,51854L,51855L,51856L,51857L,
94203 51858L,51859L,51860L,51861L,51862L,51863L,51864L,51865L,51866L,51867L,
94204 51868L,51869L,51870L,51871L,51872L,51873L,51874L,51875L,51876L,51877L,
94205 51878L,51879L,51880L,51881L,51882L,51883L,51884L,51885L,51886L,51887L,
94206 51888L,51889L,51890L,51891L,51892L,51893L,51894L,51895L,51896L,51897L,
94207 51898L,51899L,51900L,51901L,51902L,51903L,51904L,51905L,51906L,51907L,
94208 51908L,51909L,51910L,51911L,51912L,51913L,51914L,51915L,51916L,51917L,
94209 51918L,51919L,51920L,51921L,51922L,51923L,51924L,51925L,51926L,51927L,
94210 51928L,51929L,51930L,51931L,51932L,51933L,51934L,51935L,51936L,51937L,
94211 51938L,51939L,51940L,51941L,51942L,51943L,51944L,51945L,51946L,51947L,
94212 51948L,51949L,51950L,51951L,51952L,51953L,51954L,51955L,51956L,51957L,
94213 51958L,51959L,51960L,51961L,51962L,51963L,51964L,51965L,51966L,51967L,
94214 51968L,51969L,51970L,51971L,51972L,51973L,51974L,51975L,51976L,51977L,
94215 51978L,51979L,51980L,51981L,51982L,51983L,51984L,51985L,51986L,51987L,
94216 51988L,51989L,51990L,51991L,51992L,51993L,51994L,51995L,51996L,51997L,
94217 51998L,51999L,52000L,52001L,52002L,52003L,52004L,52005L,52006L,52007L,
94218 52008L,52009L,52010L,52011L,52012L,52013L,52014L,52015L,52016L,52017L,
94219 52018L,52019L,52020L,52021L,52022L,52023L,52024L,52025L,52026L,52027L,
94220 52028L,52029L,52030L,52031L,52032L,52033L,52034L,52035L,52036L,52037L,
94221 52038L,52039L,52040L,52041L,52042L,52043L,52044L,52045L,52046L,52047L,
94222 52048L,52049L,52050L,52051L,52052L,52053L,52054L,52055L,52056L,52057L,
94223 52058L,52059L,52060L,52061L,52062L,52063L,52064L,52065L,52066L,52067L,
94224 52068L,52069L,52070L,52071L,52072L,52073L,52074L,52075L,52076L,52077L,
94225 52078L,52079L,52080L,52081L,52082L,52083L,52084L,52085L,52086L,52087L,
94226 52088L,52089L,52090L,52091L,52092L,52093L,52094L,52095L,52096L,52097L,
94227 52098L,52099L,52100L,52101L,52102L,52103L,52104L,52105L,52106L,52107L,
94228 52108L,52109L,52110L,52111L,52112L,52113L,52114L,52115L,52116L,52117L,
94229 52118L,52119L,52120L,52121L,52122L,52123L,52124L,52125L,52126L,52127L,
94230 52128L,52129L,52130L,52131L,52132L,52133L,52134L,52135L,52136L,52137L,
94231 52138L,52139L,52140L,52141L,52142L,52143L,52144L,52145L,52146L,52147L,
94232 52148L,52149L,52150L,52151L,52152L,52153L,52154L,52155L,52156L,52157L,
94233 52158L,52159L,52160L,52161L,52162L,52163L,52164L,52165L,52166L,52167L,
94234 52168L,52169L,52170L,52171L,52172L,52173L,52174L,52175L,52176L,52177L,
94235 52178L,52179L,52180L,52181L,52182L,52183L,52184L,52185L,52186L,52187L,
94236 52188L,52189L,52190L,52191L,52192L,52193L,52194L,52195L,52196L,52197L,
94237 52198L,52199L,52200L,52201L,52202L,52203L,52204L,52205L,52206L,52207L,
94238 52208L,52209L,52210L,52211L,52212L,52213L,52214L,52215L,52216L,52217L,
94239 52218L,52219L,52220L,52221L,52222L,52223L,52224L,52225L,52226L,52227L,
94240 52228L,52229L,52230L,52231L,52232L,52233L,52234L,52235L,52236L,52237L,
94241 52238L,52239L,52240L,52241L,52242L,52243L,52244L,52245L,52246L,52247L,
94242 52248L,52249L,52250L,52251L,52252L,52253L,52254L,52255L,52256L,52257L,
94243 52258L,52259L,52260L,52261L,52262L,52263L,52264L,52265L,52266L,52267L,
94244 52268L,52269L,52270L,52271L,52272L,52273L,52274L,52275L,52276L,52277L,
94245 52278L,52279L,52280L,52281L,52282L,52283L,52284L,52285L,52286L,52287L,
94246 52288L,52289L,52290L,52291L,52292L,52293L,52294L,52295L,52296L,52297L,
94247 52298L,52299L,52300L,52301L,52302L,52303L,52304L,52305L,52306L,52307L,
94248 52308L,52309L,52310L,52311L,52312L,52313L,52314L,52315L,52316L,52317L,
94249 52318L,52319L,52320L,52321L,52322L,52323L,52324L,52325L,52326L,52327L,
94250 52328L,52329L,52330L,52331L,52332L,52333L,52334L,52335L,52336L,52337L,
94251 52338L,52339L,52340L,52341L,52342L,52343L,52344L,52345L,52346L,52347L,
94252 52348L,52349L,52350L,52351L,52352L,52353L,52354L,52355L,52356L,52357L,
94253 52358L,52359L,52360L,52361L,52362L,52363L,52364L,52365L,52366L,52367L,
94254 52368L,52369L,52370L,52371L,52372L,52373L,52374L,52375L,52376L,52377L,
94255 52378L,52379L,52380L,52381L,52382L,52383L,52384L,52385L,52386L,52387L,
94256 52388L,52389L,52390L,52391L,52392L,52393L,52394L,52395L,52396L,52397L,
94257 52398L,52399L,52400L,52401L,52402L,52403L,52404L,52405L,52406L,52407L,
94258 52408L,52409L,52410L,52411L,52412L,52413L,52414L,52415L,52416L,52417L,
94259 52418L,52419L,52420L,52421L,52422L,52423L,52424L,52425L,52426L,52427L,
94260 52428L,52429L,52430L,52431L,52432L,52433L,52434L,52435L,52436L,52437L,
94261 52438L,52439L,52440L,52441L,52442L,52443L,52444L,52445L,52446L,52447L,
94262 52448L,52449L,52450L,52451L,52452L,52453L,52454L,52455L,52456L,52457L,
94263 52458L,52459L,52460L,52461L,52462L,52463L,52464L,52465L,52466L,52467L,
94264 52468L,52469L,52470L,52471L,52472L,52473L,52474L,52475L,52476L,52477L,
94265 52478L,52479L,52480L,52481L,52482L,52483L,52484L,52485L,52486L,52487L,
94266 52488L,52489L,52490L,52491L,52492L,52493L,52494L,52495L,52496L,52497L,
94267 52498L,52499L,52500L,52501L,52502L,52503L,52504L,52505L,52506L,52507L,
94268 52508L,52509L,52510L,52511L,52512L,52513L,52514L,52515L,52516L,52517L,
94269 52518L,52519L,52520L,52521L,52522L,52523L,52524L,52525L,52526L,52527L,
94270 52528L,52529L,52530L,52531L,52532L,52533L,52534L,52535L,52536L,52537L,
94271 52538L,52539L,52540L,52541L,52542L,52543L,52544L,52545L,52546L,52547L,
94272 52548L,52549L,52550L,52551L,52552L,52553L,52554L,52555L,52556L,52557L,
94273 52558L,52559L,52560L,52561L,52562L,52563L,52564L,52565L,52566L,52567L,
94274 52568L,52569L,52570L,52571L,52572L,52573L,52574L,52575L,52576L,52577L,
94275 52578L,52579L,52580L,52581L,52582L,52583L,52584L,52585L,52586L,52587L,
94276 52588L,52589L,52590L,52591L,52592L,52593L,52594L,52595L,52596L,52597L,
94277 52598L,52599L,52600L,52601L,52602L,52603L,52604L,52605L,52606L,52607L,
94278 52608L,52609L,52610L,52611L,52612L,52613L,52614L,52615L,52616L,52617L,
94279 52618L,52619L,52620L,52621L,52622L,52623L,52624L,52625L,52626L,52627L,
94280 52628L,52629L,52630L,52631L,52632L,52633L,52634L,52635L,52636L,52637L,
94281 52638L,52639L,52640L,52641L,52642L,52643L,52644L,52645L,52646L,52647L,
94282 52648L,52649L,52650L,52651L,52652L,52653L,52654L,52655L,52656L,52657L,
94283 52658L,52659L,52660L,52661L,52662L,52663L,52664L,52665L,52666L,52667L,
94284 52668L,52669L,52670L,52671L,52672L,52673L,52674L,52675L,52676L,52677L,
94285 52678L,52679L,52680L,52681L,52682L,52683L,52684L,52685L,52686L,52687L,
94286 52688L,52689L,52690L,52691L,52692L,52693L,52694L,52695L,52696L,52697L,
94287 52698L,52699L,52700L,52701L,52702L,52703L,52704L,52705L,52706L,52707L,
94288 52708L,52709L,52710L,52711L,52712L,52713L,52714L,52715L,52716L,52717L,
94289 52718L,52719L,52720L,52721L,52722L,52723L,52724L,52725L,52726L,52727L,
94290 52728L,52729L,52730L,52731L,52732L,52733L,52734L,52735L,52736L,52737L,
94291 52738L,52739L,52740L,52741L,52742L,52743L,52744L,52745L,52746L,52747L,
94292 52748L,52749L,52750L,52751L,52752L,52753L,52754L,52755L,52756L,52757L,
94293 52758L,52759L,52760L,52761L,52762L,52763L,52764L,52765L,52766L,52767L,
94294 52768L,52769L,52770L,52771L,52772L,52773L,52774L,52775L,52776L,52777L,
94295 52778L,52779L,52780L,52781L,52782L,52783L,52784L,52785L,52786L,52787L,
94296 52788L,52789L,52790L,52791L,52792L,52793L,52794L,52795L,52796L,52797L,
94297 52798L,52799L,52800L,52801L,52802L,52803L,52804L,52805L,52806L,52807L,
94298 52808L,52809L,52810L,52811L,52812L,52813L,52814L,52815L,52816L,52817L,
94299 52818L,52819L,52820L,52821L,52822L,52823L,52824L,52825L,52826L,52827L,
94300 52828L,52829L,52830L,52831L,52832L,52833L,52834L,52835L,52836L,52837L,
94301 52838L,52839L,52840L,52841L,52842L,52843L,52844L,52845L,52846L,52847L,
94302 52848L,52849L,52850L,52851L,52852L,52853L,52854L,52855L,52856L,52857L,
94303 52858L,52859L,52860L,52861L,52862L,52863L,52864L,52865L,52866L,52867L,
94304 52868L,52869L,52870L,52871L,52872L,52873L,52874L,52875L,52876L,52877L,
94305 52878L,52879L,52880L,52881L,52882L,52883L,52884L,52885L,52886L,52887L,
94306 52888L,52889L,52890L,52891L,52892L,52893L,52894L,52895L,52896L,52897L,
94307 52898L,52899L,52900L,52901L,52902L,52903L,52904L,52905L,52906L,52907L,
94308 52908L,52909L,52910L,52911L,52912L,52913L,52914L,52915L,52916L,52917L,
94309 52918L,52919L,52920L,52921L,52922L,52923L,52924L,52925L,52926L,52927L,
94310 52928L,52929L,52930L,52931L,52932L,52933L,52934L,52935L,52936L,52937L,
94311 52938L,52939L,52940L,52941L,52942L,52943L,52944L,52945L,52946L,52947L,
94312 52948L,52949L,52950L,52951L,52952L,52953L,52954L,52955L,52956L,52957L,
94313 52958L,52959L,52960L,52961L,52962L,52963L,52964L,52965L,52966L,52967L,
94314 52968L,52969L,52970L,52971L,52972L,52973L,52974L,52975L,52976L,52977L,
94315 52978L,52979L,52980L,52981L,52982L,52983L,52984L,52985L,52986L,52987L,
94316 52988L,52989L,52990L,52991L,52992L,52993L,52994L,52995L,52996L,52997L,
94317 52998L,52999L,53000L,53001L,53002L,53003L,53004L,53005L,53006L,53007L,
94318 53008L,53009L,53010L,53011L,53012L,53013L,53014L,53015L,53016L,53017L,
94319 53018L,53019L,53020L,53021L,53022L,53023L,53024L,53025L,53026L,53027L,
94320 53028L,53029L,53030L,53031L,53032L,53033L,53034L,53035L,53036L,53037L,
94321 53038L,53039L,53040L,53041L,53042L,53043L,53044L,53045L,53046L,53047L,
94322 53048L,53049L,53050L,53051L,53052L,53053L,53054L,53055L,53056L,53057L,
94323 53058L,53059L,53060L,53061L,53062L,53063L,53064L,53065L,53066L,53067L,
94324 53068L,53069L,53070L,53071L,53072L,53073L,53074L,53075L,53076L,53077L,
94325 53078L,53079L,53080L,53081L,53082L,53083L,53084L,53085L,53086L,53087L,
94326 53088L,53089L,53090L,53091L,53092L,53093L,53094L,53095L,53096L,53097L,
94327 53098L,53099L,53100L,53101L,53102L,53103L,53104L,53105L,53106L,53107L,
94328 53108L,53109L,53110L,53111L,53112L,53113L,53114L,53115L,53116L,53117L,
94329 53118L,53119L,53120L,53121L,53122L,53123L,53124L,53125L,53126L,53127L,
94330 53128L,53129L,53130L,53131L,53132L,53133L,53134L,53135L,53136L,53137L,
94331 53138L,53139L,53140L,53141L,53142L,53143L,53144L,53145L,53146L,53147L,
94332 53148L,53149L,53150L,53151L,53152L,53153L,53154L,53155L,53156L,53157L,
94333 53158L,53159L,53160L,53161L,53162L,53163L,53164L,53165L,53166L,53167L,
94334 53168L,53169L,53170L,53171L,53172L,53173L,53174L,53175L,53176L,53177L,
94335 53178L,53179L,53180L,53181L,53182L,53183L,53184L,53185L,53186L,53187L,
94336 53188L,53189L,53190L,53191L,53192L,53193L,53194L,53195L,53196L,53197L,
94337 53198L,53199L,53200L,53201L,53202L,53203L,53204L,53205L,53206L,53207L,
94338 53208L,53209L,53210L,53211L,53212L,53213L,53214L,53215L,53216L,53217L,
94339 53218L,53219L,53220L,53221L,53222L,53223L,53224L,53225L,53226L,53227L,
94340 53228L,53229L,53230L,53231L,53232L,53233L,53234L,53235L,53236L,53237L,
94341 53238L,53239L,53240L,53241L,53242L,53243L,53244L,53245L,53246L,53247L,
94342 53248L,53249L,53250L,53251L,53252L,53253L,53254L,53255L,53256L,53257L,
94343 53258L,53259L,53260L,53261L,53262L,53263L,53264L,53265L,53266L,53267L,
94344 53268L,53269L,53270L,53271L,53272L,53273L,53274L,53275L,53276L,53277L,
94345 53278L,53279L,53280L,53281L,53282L,53283L,53284L,53285L,53286L,53287L,
94346 53288L,53289L,53290L,53291L,53292L,53293L,53294L,53295L,53296L,53297L,
94347 53298L,53299L,53300L,53301L,53302L,53303L,53304L,53305L,53306L,53307L,
94348 53308L,53309L,53310L,53311L,53312L,53313L,53314L,53315L,53316L,53317L,
94349 53318L,53319L,53320L,53321L,53322L,53323L,53324L,53325L,53326L,53327L,
94350 53328L,53329L,53330L,53331L,53332L,53333L,53334L,53335L,53336L,53337L,
94351 53338L,53339L,53340L,53341L,53342L,53343L,53344L,53345L,53346L,53347L,
94352 53348L,53349L,53350L,53351L,53352L,53353L,53354L,53355L,53356L,53357L,
94353 53358L,53359L,53360L,53361L,53362L,53363L,53364L,53365L,53366L,53367L,
94354 53368L,53369L,53370L,53371L,53372L,53373L,53374L,53375L,53376L,53377L,
94355 53378L,53379L,53380L,53381L,53382L,53383L,53384L,53385L,53386L,53387L,
94356 53388L,53389L,53390L,53391L,53392L,53393L,53394L,53395L,53396L,53397L,
94357 53398L,53399L,53400L,53401L,53402L,53403L,53404L,53405L,53406L,53407L,
94358 53408L,53409L,53410L,53411L,53412L,53413L,53414L,53415L,53416L,53417L,
94359 53418L,53419L,53420L,53421L,53422L,53423L,53424L,53425L,53426L,53427L,
94360 53428L,53429L,53430L,53431L,53432L,53433L,53434L,53435L,53436L,53437L,
94361 53438L,53439L,53440L,53441L,53442L,53443L,53444L,53445L,53446L,53447L,
94362 53448L,53449L,53450L,53451L,53452L,53453L,53454L,53455L,53456L,53457L,
94363 53458L,53459L,53460L,53461L,53462L,53463L,53464L,53465L,53466L,53467L,
94364 53468L,53469L,53470L,53471L,53472L,53473L,53474L,53475L,53476L,53477L,
94365 53478L,53479L,53480L,53481L,53482L,53483L,53484L,53485L,53486L,53487L,
94366 53488L,53489L,53490L,53491L,53492L,53493L,53494L,53495L,53496L,53497L,
94367 53498L,53499L,53500L,53501L,53502L,53503L,53504L,53505L,53506L,53507L,
94368 53508L,53509L,53510L,53511L,53512L,53513L,53514L,53515L,53516L,53517L,
94369 53518L,53519L,53520L,53521L,53522L,53523L,53524L,53525L,53526L,53527L,
94370 53528L,53529L,53530L,53531L,53532L,53533L,53534L,53535L,53536L,53537L,
94371 53538L,53539L,53540L,53541L,53542L,53543L,53544L,53545L,53546L,53547L,
94372 53548L,53549L,53550L,53551L,53552L,53553L,53554L,53555L,53556L,53557L,
94373 53558L,53559L,53560L,53561L,53562L,53563L,53564L,53565L,53566L,53567L,
94374 53568L,53569L,53570L,53571L,53572L,53573L,53574L,53575L,53576L,53577L,
94375 53578L,53579L,53580L,53581L,53582L,53583L,53584L,53585L,53586L,53587L,
94376 53588L,53589L,53590L,53591L,53592L,53593L,53594L,53595L,53596L,53597L,
94377 53598L,53599L,53600L,53601L,53602L,53603L,53604L,53605L,53606L,53607L,
94378 53608L,53609L,53610L,53611L,53612L,53613L,53614L,53615L,53616L,53617L,
94379 53618L,53619L,53620L,53621L,53622L,53623L,53624L,53625L,53626L,53627L,
94380 53628L,53629L,53630L,53631L,53632L,53633L,53634L,53635L,53636L,53637L,
94381 53638L,53639L,53640L,53641L,53642L,53643L,53644L,53645L,53646L,53647L,
94382 53648L,53649L,53650L,53651L,53652L,53653L,53654L,53655L,53656L,53657L,
94383 53658L,53659L,53660L,53661L,53662L,53663L,53664L,53665L,53666L,53667L,
94384 53668L,53669L,53670L,53671L,53672L,53673L,53674L,53675L,53676L,53677L,
94385 53678L,53679L,53680L,53681L,53682L,53683L,53684L,53685L,53686L,53687L,
94386 53688L,53689L,53690L,53691L,53692L,53693L,53694L,53695L,53696L,53697L,
94387 53698L,53699L,53700L,53701L,53702L,53703L,53704L,53705L,53706L,53707L,
94388 53708L,53709L,53710L,53711L,53712L,53713L,53714L,53715L,53716L,53717L,
94389 53718L,53719L,53720L,53721L,53722L,53723L,53724L,53725L,53726L,53727L,
94390 53728L,53729L,53730L,53731L,53732L,53733L,53734L,53735L,53736L,53737L,
94391 53738L,53739L,53740L,53741L,53742L,53743L,53744L,53745L,53746L,53747L,
94392 53748L,53749L,53750L,53751L,53752L,53753L,53754L,53755L,53756L,53757L,
94393 53758L,53759L,53760L,53761L,53762L,53763L,53764L,53765L,53766L,53767L,
94394 53768L,53769L,53770L,53771L,53772L,53773L,53774L,53775L,53776L,53777L,
94395 53778L,53779L,53780L,53781L,53782L,53783L,53784L,53785L,53786L,53787L,
94396 53788L,53789L,53790L,53791L,53792L,53793L,53794L,53795L,53796L,53797L,
94397 53798L,53799L,53800L,53801L,53802L,53803L,53804L,53805L,53806L,53807L,
94398 53808L,53809L,53810L,53811L,53812L,53813L,53814L,53815L,53816L,53817L,
94399 53818L,53819L,53820L,53821L,53822L,53823L,53824L,53825L,53826L,53827L,
94400 53828L,53829L,53830L,53831L,53832L,53833L,53834L,53835L,53836L,53837L,
94401 53838L,53839L,53840L,53841L,53842L,53843L,53844L,53845L,53846L,53847L,
94402 53848L,53849L,53850L,53851L,53852L,53853L,53854L,53855L,53856L,53857L,
94403 53858L,53859L,53860L,53861L,53862L,53863L,53864L,53865L,53866L,53867L,
94404 53868L,53869L,53870L,53871L,53872L,53873L,53874L,53875L,53876L,53877L,
94405 53878L,53879L,53880L,53881L,53882L,53883L,53884L,53885L,53886L,53887L,
94406 53888L,53889L,53890L,53891L,53892L,53893L,53894L,53895L,53896L,53897L,
94407 53898L,53899L,53900L,53901L,53902L,53903L,53904L,53905L,53906L,53907L,
94408 53908L,53909L,53910L,53911L,53912L,53913L,53914L,53915L,53916L,53917L,
94409 53918L,53919L,53920L,53921L,53922L,53923L,53924L,53925L,53926L,53927L,
94410 53928L,53929L,53930L,53931L,53932L,53933L,53934L,53935L,53936L,53937L,
94411 53938L,53939L,53940L,53941L,53942L,53943L,53944L,53945L,53946L,53947L,
94412 53948L,53949L,53950L,53951L,53952L,53953L,53954L,53955L,53956L,53957L,
94413 53958L,53959L,53960L,53961L,53962L,53963L,53964L,53965L,53966L,53967L,
94414 53968L,53969L,53970L,53971L,53972L,53973L,53974L,53975L,53976L,53977L,
94415 53978L,53979L,53980L,53981L,53982L,53983L,53984L,53985L,53986L,53987L,
94416 53988L,53989L,53990L,53991L,53992L,53993L,53994L,53995L,53996L,53997L,
94417 53998L,53999L,54000L,54001L,54002L,54003L,54004L,54005L,54006L,54007L,
94418 54008L,54009L,54010L,54011L,54012L,54013L,54014L,54015L,54016L,54017L,
94419 54018L,54019L,54020L,54021L,54022L,54023L,54024L,54025L,54026L,54027L,
94420 54028L,54029L,54030L,54031L,54032L,54033L,54034L,54035L,54036L,54037L,
94421 54038L,54039L,54040L,54041L,54042L,54043L,54044L,54045L,54046L,54047L,
94422 54048L,54049L,54050L,54051L,54052L,54053L,54054L,54055L,54056L,54057L,
94423 54058L,54059L,54060L,54061L,54062L,54063L,54064L,54065L,54066L,54067L,
94424 54068L,54069L,54070L,54071L,54072L,54073L,54074L,54075L,54076L,54077L,
94425 54078L,54079L,54080L,54081L,54082L,54083L,54084L,54085L,54086L,54087L,
94426 54088L,54089L,54090L,54091L,54092L,54093L,54094L,54095L,54096L,54097L,
94427 54098L,54099L,54100L,54101L,54102L,54103L,54104L,54105L,54106L,54107L,
94428 54108L,54109L,54110L,54111L,54112L,54113L,54114L,54115L,54116L,54117L,
94429 54118L,54119L,54120L,54121L,54122L,54123L,54124L,54125L,54126L,54127L,
94430 54128L,54129L,54130L,54131L,54132L,54133L,54134L,54135L,54136L,54137L,
94431 54138L,54139L,54140L,54141L,54142L,54143L,54144L,54145L,54146L,54147L,
94432 54148L,54149L,54150L,54151L,54152L,54153L,54154L,54155L,54156L,54157L,
94433 54158L,54159L,54160L,54161L,54162L,54163L,54164L,54165L,54166L,54167L,
94434 54168L,54169L,54170L,54171L,54172L,54173L,54174L,54175L,54176L,54177L,
94435 54178L,54179L,54180L,54181L,54182L,54183L,54184L,54185L,54186L,54187L,
94436 54188L,54189L,54190L,54191L,54192L,54193L,54194L,54195L,54196L,54197L,
94437 54198L,54199L,54200L,54201L,54202L,54203L,54204L,54205L,54206L,54207L,
94438 54208L,54209L,54210L,54211L,54212L,54213L,54214L,54215L,54216L,54217L,
94439 54218L,54219L,54220L,54221L,54222L,54223L,54224L,54225L,54226L,54227L,
94440 54228L,54229L,54230L,54231L,54232L,54233L,54234L,54235L,54236L,54237L,
94441 54238L,54239L,54240L,54241L,54242L,54243L,54244L,54245L,54246L,54247L,
94442 54248L,54249L,54250L,54251L,54252L,54253L,54254L,54255L,54256L,54257L,
94443 54258L,54259L,54260L,54261L,54262L,54263L,54264L,54265L,54266L,54267L,
94444 54268L,54269L,54270L,54271L,54272L,54273L,54274L,54275L,54276L,54277L,
94445 54278L,54279L,54280L,54281L,54282L,54283L,54284L,54285L,54286L,54287L,
94446 54288L,54289L,54290L,54291L,54292L,54293L,54294L,54295L,54296L,54297L,
94447 54298L,54299L,54300L,54301L,54302L,54303L,54304L,54305L,54306L,54307L,
94448 54308L,54309L,54310L,54311L,54312L,54313L,54314L,54315L,54316L,54317L,
94449 54318L,54319L,54320L,54321L,54322L,54323L,54324L,54325L,54326L,54327L,
94450 54328L,54329L,54330L,54331L,54332L,54333L,54334L,54335L,54336L,54337L,
94451 54338L,54339L,54340L,54341L,54342L,54343L,54344L,54345L,54346L,54347L,
94452 54348L,54349L,54350L,54351L,54352L,54353L,54354L,54355L,54356L,54357L,
94453 54358L,54359L,54360L,54361L,54362L,54363L,54364L,54365L,54366L,54367L,
94454 54368L,54369L,54370L,54371L,54372L,54373L,54374L,54375L,54376L,54377L,
94455 54378L,54379L,54380L,54381L,54382L,54383L,54384L,54385L,54386L,54387L,
94456 54388L,54389L,54390L,54391L,54392L,54393L,54394L,54395L,54396L,54397L,
94457 54398L,54399L,54400L,54401L,54402L,54403L,54404L,54405L,54406L,54407L,
94458 54408L,54409L,54410L,54411L,54412L,54413L,54414L,54415L,54416L,54417L,
94459 54418L,54419L,54420L,54421L,54422L,54423L,54424L,54425L,54426L,54427L,
94460 54428L,54429L,54430L,54431L,54432L,54433L,54434L,54435L,54436L,54437L,
94461 54438L,54439L,54440L,54441L,54442L,54443L,54444L,54445L,54446L,54447L,
94462 54448L,54449L,54450L,54451L,54452L,54453L,54454L,54455L,54456L,54457L,
94463 54458L,54459L,54460L,54461L,54462L,54463L,54464L,54465L,54466L,54467L,
94464 54468L,54469L,54470L,54471L,54472L,54473L,54474L,54475L,54476L,54477L,
94465 54478L,54479L,54480L,54481L,54482L,54483L,54484L,54485L,54486L,54487L,
94466 54488L,54489L,54490L,54491L,54492L,54493L,54494L,54495L,54496L,54497L,
94467 54498L,54499L,54500L,54501L,54502L,54503L,54504L,54505L,54506L,54507L,
94468 54508L,54509L,54510L,54511L,54512L,54513L,54514L,54515L,54516L,54517L,
94469 54518L,54519L,54520L,54521L,54522L,54523L,54524L,54525L,54526L,54527L,
94470 54528L,54529L,54530L,54531L,54532L,54533L,54534L,54535L,54536L,54537L,
94471 54538L,54539L,54540L,54541L,54542L,54543L,54544L,54545L,54546L,54547L,
94472 54548L,54549L,54550L,54551L,54552L,54553L,54554L,54555L,54556L,54557L,
94473 54558L,54559L,54560L,54561L,54562L,54563L,54564L,54565L,54566L,54567L,
94474 54568L,54569L,54570L,54571L,54572L,54573L,54574L,54575L,54576L,54577L,
94475 54578L,54579L,54580L,54581L,54582L,54583L,54584L,54585L,54586L,54587L,
94476 54588L,54589L,54590L,54591L,54592L,54593L,54594L,54595L,54596L,54597L,
94477 54598L,54599L,54600L,54601L,54602L,54603L,54604L,54605L,54606L,54607L,
94478 54608L,54609L,54610L,54611L,54612L,54613L,54614L,54615L,54616L,54617L,
94479 54618L,54619L,54620L,54621L,54622L,54623L,54624L,54625L,54626L,54627L,
94480 54628L,54629L,54630L,54631L,54632L,54633L,54634L,54635L,54636L,54637L,
94481 54638L,54639L,54640L,54641L,54642L,54643L,54644L,54645L,54646L,54647L,
94482 54648L,54649L,54650L,54651L,54652L,54653L,54654L,54655L,54656L,54657L,
94483 54658L,54659L,54660L,54661L,54662L,54663L,54664L,54665L,54666L,54667L,
94484 54668L,54669L,54670L,54671L,54672L,54673L,54674L,54675L,54676L,54677L,
94485 54678L,54679L,54680L,54681L,54682L,54683L,54684L,54685L,54686L,54687L,
94486 54688L,54689L,54690L,54691L,54692L,54693L,54694L,54695L,54696L,54697L,
94487 54698L,54699L,54700L,54701L,54702L,54703L,54704L,54705L,54706L,54707L,
94488 54708L,54709L,54710L,54711L,54712L,54713L,54714L,54715L,54716L,54717L,
94489 54718L,54719L,54720L,54721L,54722L,54723L,54724L,54725L,54726L,54727L,
94490 54728L,54729L,54730L,54731L,54732L,54733L,54734L,54735L,54736L,54737L,
94491 54738L,54739L,54740L,54741L,54742L,54743L,54744L,54745L,54746L,54747L,
94492 54748L,54749L,54750L,54751L,54752L,54753L,54754L,54755L,54756L,54757L,
94493 54758L,54759L,54760L,54761L,54762L,54763L,54764L,54765L,54766L,54767L,
94494 54768L,54769L,54770L,54771L,54772L,54773L,54774L,54775L,54776L,54777L,
94495 54778L,54779L,54780L,54781L,54782L,54783L,54784L,54785L,54786L,54787L,
94496 54788L,54789L,54790L,54791L,54792L,54793L,54794L,54795L,54796L,54797L,
94497 54798L,54799L,54800L,54801L,54802L,54803L,54804L,54805L,54806L,54807L,
94498 54808L,54809L,54810L,54811L,54812L,54813L,54814L,54815L,54816L,54817L,
94499 54818L,54819L,54820L,54821L,54822L,54823L,54824L,54825L,54826L,54827L,
94500 54828L,54829L,54830L,54831L,54832L,54833L,54834L,54835L,54836L,54837L,
94501 54838L,54839L,54840L,54841L,54842L,54843L,54844L,54845L,54846L,54847L,
94502 54848L,54849L,54850L,54851L,54852L,54853L,54854L,54855L,54856L,54857L,
94503 54858L,54859L,54860L,54861L,54862L,54863L,54864L,54865L,54866L,54867L,
94504 54868L,54869L,54870L,54871L,54872L,54873L,54874L,54875L,54876L,54877L,
94505 54878L,54879L,54880L,54881L,54882L,54883L,54884L,54885L,54886L,54887L,
94506 54888L,54889L,54890L,54891L,54892L,54893L,54894L,54895L,54896L,54897L,
94507 54898L,54899L,54900L,54901L,54902L,54903L,54904L,54905L,54906L,54907L,
94508 54908L,54909L,54910L,54911L,54912L,54913L,54914L,54915L,54916L,54917L,
94509 54918L,54919L,54920L,54921L,54922L,54923L,54924L,54925L,54926L,54927L,
94510 54928L,54929L,54930L,54931L,54932L,54933L,54934L,54935L,54936L,54937L,
94511 54938L,54939L,54940L,54941L,54942L,54943L,54944L,54945L,54946L,54947L,
94512 54948L,54949L,54950L,54951L,54952L,54953L,54954L,54955L,54956L,54957L,
94513 54958L,54959L,54960L,54961L,54962L,54963L,54964L,54965L,54966L,54967L,
94514 54968L,54969L,54970L,54971L,54972L,54973L,54974L,54975L,54976L,54977L,
94515 54978L,54979L,54980L,54981L,54982L,54983L,54984L,54985L,54986L,54987L,
94516 54988L,54989L,54990L,54991L,54992L,54993L,54994L,54995L,54996L,54997L,
94517 54998L,54999L,55000L,55001L,55002L,55003L,55004L,55005L,55006L,55007L,
94518 55008L,55009L,55010L,55011L,55012L,55013L,55014L,55015L,55016L,55017L,
94519 55018L,55019L,55020L,55021L,55022L,55023L,55024L,55025L,55026L,55027L,
94520 55028L,55029L,55030L,55031L,55032L,55033L,55034L,55035L,55036L,55037L,
94521 55038L,55039L,55040L,55041L,55042L,55043L,55044L,55045L,55046L,55047L,
94522 55048L,55049L,55050L,55051L,55052L,55053L,55054L,55055L,55056L,55057L,
94523 55058L,55059L,55060L,55061L,55062L,55063L,55064L,55065L,55066L,55067L,
94524 55068L,55069L,55070L,55071L,55072L,55073L,55074L,55075L,55076L,55077L,
94525 55078L,55079L,55080L,55081L,55082L,55083L,55084L,55085L,55086L,55087L,
94526 55088L,55089L,55090L,55091L,55092L,55093L,55094L,55095L,55096L,55097L,
94527 55098L,55099L,55100L,55101L,55102L,55103L,55104L,55105L,55106L,55107L,
94528 55108L,55109L,55110L,55111L,55112L,55113L,55114L,55115L,55116L,55117L,
94529 55118L,55119L,55120L,55121L,55122L,55123L,55124L,55125L,55126L,55127L,
94530 55128L,55129L,55130L,55131L,55132L,55133L,55134L,55135L,55136L,55137L,
94531 55138L,55139L,55140L,55141L,55142L,55143L,55144L,55145L,55146L,55147L,
94532 55148L,55149L,55150L,55151L,55152L,55153L,55154L,55155L,55156L,55157L,
94533 55158L,55159L,55160L,55161L,55162L,55163L,55164L,55165L,55166L,55167L,
94534 55168L,55169L,55170L,55171L,55172L,55173L,55174L,55175L,55176L,55177L,
94535 55178L,55179L,55180L,55181L,55182L,55183L,55184L,55185L,55186L,55187L,
94536 55188L,55189L,55190L,55191L,55192L,55193L,55194L,55195L,55196L,55197L,
94537 55198L,55199L,55200L,55201L,55202L,55203L,55204L,55205L,55206L,55207L,
94538 55208L,55209L,55210L,55211L,55212L,55213L,55214L,55215L,55216L,55217L,
94539 55218L,55219L,55220L,55221L,55222L,55223L,55224L,55225L,55226L,55227L,
94540 55228L,55229L,55230L,55231L,55232L,55233L,55234L,55235L,55236L,55237L,
94541 55238L,55239L,55240L,55241L,55242L,55243L,55244L,55245L,55246L,55247L,
94542 55248L,55249L,55250L,55251L,55252L,55253L,55254L,55255L,55256L,55257L,
94543 55258L,55259L,55260L,55261L,55262L,55263L,55264L,55265L,55266L,55267L,
94544 55268L,55269L,55270L,55271L,55272L,55273L,55274L,55275L,55276L,55277L,
94545 55278L,55279L,55280L,55281L,55282L,55283L,55284L,55285L,55286L,55287L,
94546 55288L,55289L,55290L,55291L,55292L,55293L,55294L,55295L,55296L,55297L,
94547 55298L,55299L,55300L,55301L,55302L,55303L,55304L,55305L,55306L,55307L,
94548 55308L,55309L,55310L,55311L,55312L,55313L,55314L,55315L,55316L,55317L,
94549 55318L,55319L,55320L,55321L,55322L,55323L,55324L,55325L,55326L,55327L,
94550 55328L,55329L,55330L,55331L,55332L,55333L,55334L,55335L,55336L,55337L,
94551 55338L,55339L,55340L,55341L,55342L,55343L,55344L,55345L,55346L,55347L,
94552 55348L,55349L,55350L,55351L,55352L,55353L,55354L,55355L,55356L,55357L,
94553 55358L,55359L,55360L,55361L,55362L,55363L,55364L,55365L,55366L,55367L,
94554 55368L,55369L,55370L,55371L,55372L,55373L,55374L,55375L,55376L,55377L,
94555 55378L,55379L,55380L,55381L,55382L,55383L,55384L,55385L,55386L,55387L,
94556 55388L,55389L,55390L,55391L,55392L,55393L,55394L,55395L,55396L,55397L,
94557 55398L,55399L,55400L,55401L,55402L,55403L,55404L,55405L,55406L,55407L,
94558 55408L,55409L,55410L,55411L,55412L,55413L,55414L,55415L,55416L,55417L,
94559 55418L,55419L,55420L,55421L,55422L,55423L,55424L,55425L,55426L,55427L,
94560 55428L,55429L,55430L,55431L,55432L,55433L,55434L,55435L,55436L,55437L,
94561 55438L,55439L,55440L,55441L,55442L,55443L,55444L,55445L,55446L,55447L,
94562 55448L,55449L,55450L,55451L,55452L,55453L,55454L,55455L,55456L,55457L,
94563 55458L,55459L,55460L,55461L,55462L,55463L,55464L,55465L,55466L,55467L,
94564 55468L,55469L,55470L,55471L,55472L,55473L,55474L,55475L,55476L,55477L,
94565 55478L,55479L,55480L,55481L,55482L,55483L,55484L,55485L,55486L,55487L,
94566 55488L,55489L,55490L,55491L,55492L,55493L,55494L,55495L,55496L,55497L,
94567 55498L,55499L,55500L,55501L,55502L,55503L,55504L,55505L,55506L,55507L,
94568 55508L,55509L,55510L,55511L,55512L,55513L,55514L,55515L,55516L,55517L,
94569 55518L,55519L,55520L,55521L,55522L,55523L,55524L,55525L,55526L,55527L,
94570 55528L,55529L,55530L,55531L,55532L,55533L,55534L,55535L,55536L,55537L,
94571 55538L,55539L,55540L,55541L,55542L,55543L,55544L,55545L,55546L,55547L,
94572 55548L,55549L,55550L,55551L,55552L,55553L,55554L,55555L,55556L,55557L,
94573 55558L,55559L,55560L,55561L,55562L,55563L,55564L,55565L,55566L,55567L,
94574 55568L,55569L,55570L,55571L,55572L,55573L,55574L,55575L,55576L,55577L,
94575 55578L,55579L,55580L,55581L,55582L,55583L,55584L,55585L,55586L,55587L,
94576 55588L,55589L,55590L,55591L,55592L,55593L,55594L,55595L,55596L,55597L,
94577 55598L,55599L,55600L,55601L,55602L,55603L,55604L,55605L,55606L,55607L,
94578 55608L,55609L,55610L,55611L,55612L,55613L,55614L,55615L,55616L,55617L,
94579 55618L,55619L,55620L,55621L,55622L,55623L,55624L,55625L,55626L,55627L,
94580 55628L,55629L,55630L,55631L,55632L,55633L,55634L,55635L,55636L,55637L,
94581 55638L,55639L,55640L,55641L,55642L,55643L,55644L,55645L,55646L,55647L,
94582 55648L,55649L,55650L,55651L,55652L,55653L,55654L,55655L,55656L,55657L,
94583 55658L,55659L,55660L,55661L,55662L,55663L,55664L,55665L,55666L,55667L,
94584 55668L,55669L,55670L,55671L,55672L,55673L,55674L,55675L,55676L,55677L,
94585 55678L,55679L,55680L,55681L,55682L,55683L,55684L,55685L,55686L,55687L,
94586 55688L,55689L,55690L,55691L,55692L,55693L,55694L,55695L,55696L,55697L,
94587 55698L,55699L,55700L,55701L,55702L,55703L,55704L,55705L,55706L,55707L,
94588 55708L,55709L,55710L,55711L,55712L,55713L,55714L,55715L,55716L,55717L,
94589 55718L,55719L,55720L,55721L,55722L,55723L,55724L,55725L,55726L,55727L,
94590 55728L,55729L,55730L,55731L,55732L,55733L,55734L,55735L,55736L,55737L,
94591 55738L,55739L,55740L,55741L,55742L,55743L,55744L,55745L,55746L,55747L,
94592 55748L,55749L,55750L,55751L,55752L,55753L,55754L,55755L,55756L,55757L,
94593 55758L,55759L,55760L,55761L,55762L,55763L,55764L,55765L,55766L,55767L,
94594 55768L,55769L,55770L,55771L,55772L,55773L,55774L,55775L,55776L,55777L,
94595 55778L,55779L,55780L,55781L,55782L,55783L,55784L,55785L,55786L,55787L,
94596 55788L,55789L,55790L,55791L,55792L,55793L,55794L,55795L,55796L,55797L,
94597 55798L,55799L,55800L,55801L,55802L,55803L,55804L,55805L,55806L,55807L,
94598 55808L,55809L,55810L,55811L,55812L,55813L,55814L,55815L,55816L,55817L,
94599 55818L,55819L,55820L,55821L,55822L,55823L,55824L,55825L,55826L,55827L,
94600 55828L,55829L,55830L,55831L,55832L,55833L,55834L,55835L,55836L,55837L,
94601 55838L,55839L,55840L,55841L,55842L,55843L,55844L,55845L,55846L,55847L,
94602 55848L,55849L,55850L,55851L,55852L,55853L,55854L,55855L,55856L,55857L,
94603 55858L,55859L,55860L,55861L,55862L,55863L,55864L,55865L,55866L,55867L,
94604 55868L,55869L,55870L,55871L,55872L,55873L,55874L,55875L,55876L,55877L,
94605 55878L,55879L,55880L,55881L,55882L,55883L,55884L,55885L,55886L,55887L,
94606 55888L,55889L,55890L,55891L,55892L,55893L,55894L,55895L,55896L,55897L,
94607 55898L,55899L,55900L,55901L,55902L,55903L,55904L,55905L,55906L,55907L,
94608 55908L,55909L,55910L,55911L,55912L,55913L,55914L,55915L,55916L,55917L,
94609 55918L,55919L,55920L,55921L,55922L,55923L,55924L,55925L,55926L,55927L,
94610 55928L,55929L,55930L,55931L,55932L,55933L,55934L,55935L,55936L,55937L,
94611 55938L,55939L,55940L,55941L,55942L,55943L,55944L,55945L,55946L,55947L,
94612 55948L,55949L,55950L,55951L,55952L,55953L,55954L,55955L,55956L,55957L,
94613 55958L,55959L,55960L,55961L,55962L,55963L,55964L,55965L,55966L,55967L,
94614 55968L,55969L,55970L,55971L,55972L,55973L,55974L,55975L,55976L,55977L,
94615 55978L,55979L,55980L,55981L,55982L,55983L,55984L,55985L,55986L,55987L,
94616 55988L,55989L,55990L,55991L,55992L,55993L,55994L,55995L,55996L,55997L,
94617 55998L,55999L,56000L,56001L,56002L,56003L,56004L,56005L,56006L,56007L,
94618 56008L,56009L,56010L,56011L,56012L,56013L,56014L,56015L,56016L,56017L,
94619 56018L,56019L,56020L,56021L,56022L,56023L,56024L,56025L,56026L,56027L,
94620 56028L,56029L,56030L,56031L,56032L,56033L,56034L,56035L,56036L,56037L,
94621 56038L,56039L,56040L,56041L,56042L,56043L,56044L,56045L,56046L,56047L,
94622 56048L,56049L,56050L,56051L,56052L,56053L,56054L,56055L,56056L,56057L,
94623 56058L,56059L,56060L,56061L,56062L,56063L,56064L,56065L,56066L,56067L,
94624 56068L,56069L,56070L,56071L,56072L,56073L,56074L,56075L,56076L,56077L,
94625 56078L,56079L,56080L,56081L,56082L,56083L,56084L,56085L,56086L,56087L,
94626 56088L,56089L,56090L,56091L,56092L,56093L,56094L,56095L,56096L,56097L,
94627 56098L,56099L,56100L,56101L,56102L,56103L,56104L,56105L,56106L,56107L,
94628 56108L,56109L,56110L,56111L,56112L,56113L,56114L,56115L,56116L,56117L,
94629 56118L,56119L,56120L,56121L,56122L,56123L,56124L,56125L,56126L,56127L,
94630 56128L,56129L,56130L,56131L,56132L,56133L,56134L,56135L,56136L,56137L,
94631 56138L,56139L,56140L,56141L,56142L,56143L,56144L,56145L,56146L,56147L,
94632 56148L,56149L,56150L,56151L,56152L,56153L,56154L,56155L,56156L,56157L,
94633 56158L,56159L,56160L,56161L,56162L,56163L,56164L,56165L,56166L,56167L,
94634 56168L,56169L,56170L,56171L,56172L,56173L,56174L,56175L,56176L,56177L,
94635 56178L,56179L,56180L,56181L,56182L,56183L,56184L,56185L,56186L,56187L,
94636 56188L,56189L,56190L,56191L,56192L,56193L,56194L,56195L,56196L,56197L,
94637 56198L,56199L,56200L,56201L,56202L,56203L,56204L,56205L,56206L,56207L,
94638 56208L,56209L,56210L,56211L,56212L,56213L,56214L,56215L,56216L,56217L,
94639 56218L,56219L,56220L,56221L,56222L,56223L,56224L,56225L,56226L,56227L,
94640 56228L,56229L,56230L,56231L,56232L,56233L,56234L,56235L,56236L,56237L,
94641 56238L,56239L,56240L,56241L,56242L,56243L,56244L,56245L,56246L,56247L,
94642 56248L,56249L,56250L,56251L,56252L,56253L,56254L,56255L,56256L,56257L,
94643 56258L,56259L,56260L,56261L,56262L,56263L,56264L,56265L,56266L,56267L,
94644 56268L,56269L,56270L,56271L,56272L,56273L,56274L,56275L,56276L,56277L,
94645 56278L,56279L,56280L,56281L,56282L,56283L,56284L,56285L,56286L,56287L,
94646 56288L,56289L,56290L,56291L,56292L,56293L,56294L,56295L,56296L,56297L,
94647 56298L,56299L,56300L,56301L,56302L,56303L,56304L,56305L,56306L,56307L,
94648 56308L,56309L,56310L,56311L,56312L,56313L,56314L,56315L,56316L,56317L,
94649 56318L,56319L,56320L,56321L,56322L,56323L,56324L,56325L,56326L,56327L,
94650 56328L,56329L,56330L,56331L,56332L,56333L,56334L,56335L,56336L,56337L,
94651 56338L,56339L,56340L,56341L,56342L,56343L,56344L,56345L,56346L,56347L,
94652 56348L,56349L,56350L,56351L,56352L,56353L,56354L,56355L,56356L,56357L,
94653 56358L,56359L,56360L,56361L,56362L,56363L,56364L,56365L,56366L,56367L,
94654 56368L,56369L,56370L,56371L,56372L,56373L,56374L,56375L,56376L,56377L,
94655 56378L,56379L,56380L,56381L,56382L,56383L,56384L,56385L,56386L,56387L,
94656 56388L,56389L,56390L,56391L,56392L,56393L,56394L,56395L,56396L,56397L,
94657 56398L,56399L,56400L,56401L,56402L,56403L,56404L,56405L,56406L,56407L,
94658 56408L,56409L,56410L,56411L,56412L,56413L,56414L,56415L,56416L,56417L,
94659 56418L,56419L,56420L,56421L,56422L,56423L,56424L,56425L,56426L,56427L,
94660 56428L,56429L,56430L,56431L,56432L,56433L,56434L,56435L,56436L,56437L,
94661 56438L,56439L,56440L,56441L,56442L,56443L,56444L,56445L,56446L,56447L,
94662 56448L,56449L,56450L,56451L,56452L,56453L,56454L,56455L,56456L,56457L,
94663 56458L,56459L,56460L,56461L,56462L,56463L,56464L,56465L,56466L,56467L,
94664 56468L,56469L,56470L,56471L,56472L,56473L,56474L,56475L,56476L,56477L,
94665 56478L,56479L,56480L,56481L,56482L,56483L,56484L,56485L,56486L,56487L,
94666 56488L,56489L,56490L,56491L,56492L,56493L,56494L,56495L,56496L,56497L,
94667 56498L,56499L,56500L,56501L,56502L,56503L,56504L,56505L,56506L,56507L,
94668 56508L,56509L,56510L,56511L,56512L,56513L,56514L,56515L,56516L,56517L,
94669 56518L,56519L,56520L,56521L,56522L,56523L,56524L,56525L,56526L,56527L,
94670 56528L,56529L,56530L,56531L,56532L,56533L,56534L,56535L,56536L,56537L,
94671 56538L,56539L,56540L,56541L,56542L,56543L,56544L,56545L,56546L,56547L,
94672 56548L,56549L,56550L,56551L,56552L,56553L,56554L,56555L,56556L,56557L,
94673 56558L,56559L,56560L,56561L,56562L,56563L,56564L,56565L,56566L,56567L,
94674 56568L,56569L,56570L,56571L,56572L,56573L,56574L,56575L,56576L,56577L,
94675 56578L,56579L,56580L,56581L,56582L,56583L,56584L,56585L,56586L,56587L,
94676 56588L,56589L,56590L,56591L,56592L,56593L,56594L,56595L,56596L,56597L,
94677 56598L,56599L,56600L,56601L,56602L,56603L,56604L,56605L,56606L,56607L,
94678 56608L,56609L,56610L,56611L,56612L,56613L,56614L,56615L,56616L,56617L,
94679 56618L,56619L,56620L,56621L,56622L,56623L,56624L,56625L,56626L,56627L,
94680 56628L,56629L,56630L,56631L,56632L,56633L,56634L,56635L,56636L,56637L,
94681 56638L,56639L,56640L,56641L,56642L,56643L,56644L,56645L,56646L,56647L,
94682 56648L,56649L,56650L,56651L,56652L,56653L,56654L,56655L,56656L,56657L,
94683 56658L,56659L,56660L,56661L,56662L,56663L,56664L,56665L,56666L,56667L,
94684 56668L,56669L,56670L,56671L,56672L,56673L,56674L,56675L,56676L,56677L,
94685 56678L,56679L,56680L,56681L,56682L,56683L,56684L,56685L,56686L,56687L,
94686 56688L,56689L,56690L,56691L,56692L,56693L,56694L,56695L,56696L,56697L,
94687 56698L,56699L,56700L,56701L,56702L,56703L,56704L,56705L,56706L,56707L,
94688 56708L,56709L,56710L,56711L,56712L,56713L,56714L,56715L,56716L,56717L,
94689 56718L,56719L,56720L,56721L,56722L,56723L,56724L,56725L,56726L,56727L,
94690 56728L,56729L,56730L,56731L,56732L,56733L,56734L,56735L,56736L,56737L,
94691 56738L,56739L,56740L,56741L,56742L,56743L,56744L,56745L,56746L,56747L,
94692 56748L,56749L,56750L,56751L,56752L,56753L,56754L,56755L,56756L,56757L,
94693 56758L,56759L,56760L,56761L,56762L,56763L,56764L,56765L,56766L,56767L,
94694 56768L,56769L,56770L,56771L,56772L,56773L,56774L,56775L,56776L,56777L,
94695 56778L,56779L,56780L,56781L,56782L,56783L,56784L,56785L,56786L,56787L,
94696 56788L,56789L,56790L,56791L,56792L,56793L,56794L,56795L,56796L,56797L,
94697 56798L,56799L,56800L,56801L,56802L,56803L,56804L,56805L,56806L,56807L,
94698 56808L,56809L,56810L,56811L,56812L,56813L,56814L,56815L,56816L,56817L,
94699 56818L,56819L,56820L,56821L,56822L,56823L,56824L,56825L,56826L,56827L,
94700 56828L,56829L,56830L,56831L,56832L,56833L,56834L,56835L,56836L,56837L,
94701 56838L,56839L,56840L,56841L,56842L,56843L,56844L,56845L,56846L,56847L,
94702 56848L,56849L,56850L,56851L,56852L,56853L,56854L,56855L,56856L,56857L,
94703 56858L,56859L,56860L,56861L,56862L,56863L,56864L,56865L,56866L,56867L,
94704 56868L,56869L,56870L,56871L,56872L,56873L,56874L,56875L,56876L,56877L,
94705 56878L,56879L,56880L,56881L,56882L,56883L,56884L,56885L,56886L,56887L,
94706 56888L,56889L,56890L,56891L,56892L,56893L,56894L,56895L,56896L,56897L,
94707 56898L,56899L,56900L,56901L,56902L,56903L,56904L,56905L,56906L,56907L,
94708 56908L,56909L,56910L,56911L,56912L,56913L,56914L,56915L,56916L,56917L,
94709 56918L,56919L,56920L,56921L,56922L,56923L,56924L,56925L,56926L,56927L,
94710 56928L,56929L,56930L,56931L,56932L,56933L,56934L,56935L,56936L,56937L,
94711 56938L,56939L,56940L,56941L,56942L,56943L,56944L,56945L,56946L,56947L,
94712 56948L,56949L,56950L,56951L,56952L,56953L,56954L,56955L,56956L,56957L,
94713 56958L,56959L,56960L,56961L,56962L,56963L,56964L,56965L,56966L,56967L,
94714 56968L,56969L,56970L,56971L,56972L,56973L,56974L,56975L,56976L,56977L,
94715 56978L,56979L,56980L,56981L,56982L,56983L,56984L,56985L,56986L,56987L,
94716 56988L,56989L,56990L,56991L,56992L,56993L,56994L,56995L,56996L,56997L,
94717 56998L,56999L,57000L,57001L,57002L,57003L,57004L,57005L,57006L,57007L,
94718 57008L,57009L,57010L,57011L,57012L,57013L,57014L,57015L,57016L,57017L,
94719 57018L,57019L,57020L,57021L,57022L,57023L,57024L,57025L,57026L,57027L,
94720 57028L,57029L,57030L,57031L,57032L,57033L,57034L,57035L,57036L,57037L,
94721 57038L,57039L,57040L,57041L,57042L,57043L,57044L,57045L,57046L,57047L,
94722 57048L,57049L,57050L,57051L,57052L,57053L,57054L,57055L,57056L,57057L,
94723 57058L,57059L,57060L,57061L,57062L,57063L,57064L,57065L,57066L,57067L,
94724 57068L,57069L,57070L,57071L,57072L,57073L,57074L,57075L,57076L,57077L,
94725 57078L,57079L,57080L,57081L,57082L,57083L,57084L,57085L,57086L,57087L,
94726 57088L,57089L,57090L,57091L,57092L,57093L,57094L,57095L,57096L,57097L,
94727 57098L,57099L,57100L,57101L,57102L,57103L,57104L,57105L,57106L,57107L,
94728 57108L,57109L,57110L,57111L,57112L,57113L,57114L,57115L,57116L,57117L,
94729 57118L,57119L,57120L,57121L,57122L,57123L,57124L,57125L,57126L,57127L,
94730 57128L,57129L,57130L,57131L,57132L,57133L,57134L,57135L,57136L,57137L,
94731 57138L,57139L,57140L,57141L,57142L,57143L,57144L,57145L,57146L,57147L,
94732 57148L,57149L,57150L,57151L,57152L,57153L,57154L,57155L,57156L,57157L,
94733 57158L,57159L,57160L,57161L,57162L,57163L,57164L,57165L,57166L,57167L,
94734 57168L,57169L,57170L,57171L,57172L,57173L,57174L,57175L,57176L,57177L,
94735 57178L,57179L,57180L,57181L,57182L,57183L,57184L,57185L,57186L,57187L,
94736 57188L,57189L,57190L,57191L,57192L,57193L,57194L,57195L,57196L,57197L,
94737 57198L,57199L,57200L,57201L,57202L,57203L,57204L,57205L,57206L,57207L,
94738 57208L,57209L,57210L,57211L,57212L,57213L,57214L,57215L,57216L,57217L,
94739 57218L,57219L,57220L,57221L,57222L,57223L,57224L,57225L,57226L,57227L,
94740 57228L,57229L,57230L,57231L,57232L,57233L,57234L,57235L,57236L,57237L,
94741 57238L,57239L,57240L,57241L,57242L,57243L,57244L,57245L,57246L,57247L,
94742 57248L,57249L,57250L,57251L,57252L,57253L,57254L,57255L,57256L,57257L,
94743 57258L,57259L,57260L,57261L,57262L,57263L,57264L,57265L,57266L,57267L,
94744 57268L,57269L,57270L,57271L,57272L,57273L,57274L,57275L,57276L,57277L,
94745 57278L,57279L,57280L,57281L,57282L,57283L,57284L,57285L,57286L,57287L,
94746 57288L,57289L,57290L,57291L,57292L,57293L,57294L,57295L,57296L,57297L,
94747 57298L,57299L,57300L,57301L,57302L,57303L,57304L,57305L,57306L,57307L,
94748 57308L,57309L,57310L,57311L,57312L,57313L,57314L,57315L,57316L,57317L,
94749 57318L,57319L,57320L,57321L,57322L,57323L,57324L,57325L,57326L,57327L,
94750 57328L,57329L,57330L,57331L,57332L,57333L,57334L,57335L,57336L,57337L,
94751 57338L,57339L,57340L,57341L,57342L,57343L,57344L,57345L,57346L,57347L,
94752 57348L,57349L,57350L,57351L,57352L,57353L,57354L,57355L,57356L,57357L,
94753 57358L,57359L,57360L,57361L,57362L,57363L,57364L,57365L,57366L,57367L,
94754 57368L,57369L,57370L,57371L,57372L,57373L,57374L,57375L,57376L,57377L,
94755 57378L,57379L,57380L,57381L,57382L,57383L,57384L,57385L,57386L,57387L,
94756 57388L,57389L,57390L,57391L,57392L,57393L,57394L,57395L,57396L,57397L,
94757 57398L,57399L,57400L,57401L,57402L,57403L,57404L,57405L,57406L,57407L,
94758 57408L,57409L,57410L,57411L,57412L,57413L,57414L,57415L,57416L,57417L,
94759 57418L,57419L,57420L,57421L,57422L,57423L,57424L,57425L,57426L,57427L,
94760 57428L,57429L,57430L,57431L,57432L,57433L,57434L,57435L,57436L,57437L,
94761 57438L,57439L,57440L,57441L,57442L,57443L,57444L,57445L,57446L,57447L,
94762 57448L,57449L,57450L,57451L,57452L,57453L,57454L,57455L,57456L,57457L,
94763 57458L,57459L,57460L,57461L,57462L,57463L,57464L,57465L,57466L,57467L,
94764 57468L,57469L,57470L,57471L,57472L,57473L,57474L,57475L,57476L,57477L,
94765 57478L,57479L,57480L,57481L,57482L,57483L,57484L,57485L,57486L,57487L,
94766 57488L,57489L,57490L,57491L,57492L,57493L,57494L,57495L,57496L,57497L,
94767 57498L,57499L,57500L,57501L,57502L,57503L,57504L,57505L,57506L,57507L,
94768 57508L,57509L,57510L,57511L,57512L,57513L,57514L,57515L,57516L,57517L,
94769 57518L,57519L,57520L,57521L,57522L,57523L,57524L,57525L,57526L,57527L,
94770 57528L,57529L,57530L,57531L,57532L,57533L,57534L,57535L,57536L,57537L,
94771 57538L,57539L,57540L,57541L,57542L,57543L,57544L,57545L,57546L,57547L,
94772 57548L,57549L,57550L,57551L,57552L,57553L,57554L,57555L,57556L,57557L,
94773 57558L,57559L,57560L,57561L,57562L,57563L,57564L,57565L,57566L,57567L,
94774 57568L,57569L,57570L,57571L,57572L,57573L,57574L,57575L,57576L,57577L,
94775 57578L,57579L,57580L,57581L,57582L,57583L,57584L,57585L,57586L,57587L,
94776 57588L,57589L,57590L,57591L,57592L,57593L,57594L,57595L,57596L,57597L,
94777 57598L,57599L,57600L,57601L,57602L,57603L,57604L,57605L,57606L,57607L,
94778 57608L,57609L,57610L,57611L,57612L,57613L,57614L,57615L,57616L,57617L,
94779 57618L,57619L,57620L,57621L,57622L,57623L,57624L,57625L,57626L,57627L,
94780 57628L,57629L,57630L,57631L,57632L,57633L,57634L,57635L,57636L,57637L,
94781 57638L,57639L,57640L,57641L,57642L,57643L,57644L,57645L,57646L,57647L,
94782 57648L,57649L,57650L,57651L,57652L,57653L,57654L,57655L,57656L,57657L,
94783 57658L,57659L,57660L,57661L,57662L,57663L,57664L,57665L,57666L,57667L,
94784 57668L,57669L,57670L,57671L,57672L,57673L,57674L,57675L,57676L,57677L,
94785 57678L,57679L,57680L,57681L,57682L,57683L,57684L,57685L,57686L,57687L,
94786 57688L,57689L,57690L,57691L,57692L,57693L,57694L,57695L,57696L,57697L,
94787 57698L,57699L,57700L,57701L,57702L,57703L,57704L,57705L,57706L,57707L,
94788 57708L,57709L,57710L,57711L,57712L,57713L,57714L,57715L,57716L,57717L,
94789 57718L,57719L,57720L,57721L,57722L,57723L,57724L,57725L,57726L,57727L,
94790 57728L,57729L,57730L,57731L,57732L,57733L,57734L,57735L,57736L,57737L,
94791 57738L,57739L,57740L,57741L,57742L,57743L,57744L,57745L,57746L,57747L,
94792 57748L,57749L,57750L,57751L,57752L,57753L,57754L,57755L,57756L,57757L,
94793 57758L,57759L,57760L,57761L,57762L,57763L,57764L,57765L,57766L,57767L,
94794 57768L,57769L,57770L,57771L,57772L,57773L,57774L,57775L,57776L,57777L,
94795 57778L,57779L,57780L,57781L,57782L,57783L,57784L,57785L,57786L,57787L,
94796 57788L,57789L,57790L,57791L,57792L,57793L,57794L,57795L,57796L,57797L,
94797 57798L,57799L,57800L,57801L,57802L,57803L,57804L,57805L,57806L,57807L,
94798 57808L,57809L,57810L,57811L,57812L,57813L,57814L,57815L,57816L,57817L,
94799 57818L,57819L,57820L,57821L,57822L,57823L,57824L,57825L,57826L,57827L,
94800 57828L,57829L,57830L,57831L,57832L,57833L,57834L,57835L,57836L,57837L,
94801 57838L,57839L,57840L,57841L,57842L,57843L,57844L,57845L,57846L,57847L,
94802 57848L,57849L,57850L,57851L,57852L,57853L,57854L,57855L,57856L,57857L,
94803 57858L,57859L,57860L,57861L,57862L,57863L,57864L,57865L,57866L,57867L,
94804 57868L,57869L,57870L,57871L,57872L,57873L,57874L,57875L,57876L,57877L,
94805 57878L,57879L,57880L,57881L,57882L,57883L,57884L,57885L,57886L,57887L,
94806 57888L,57889L,57890L,57891L,57892L,57893L,57894L,57895L,57896L,57897L,
94807 57898L,57899L,57900L,57901L,57902L,57903L,57904L,57905L,57906L,57907L,
94808 57908L,57909L,57910L,57911L,57912L,57913L,57914L,57915L,57916L,57917L,
94809 57918L,57919L,57920L,57921L,57922L,57923L,57924L,57925L,57926L,57927L,
94810 57928L,57929L,57930L,57931L,57932L,57933L,57934L,57935L,57936L,57937L,
94811 57938L,57939L,57940L,57941L,57942L,57943L,57944L,57945L,57946L,57947L,
94812 57948L,57949L,57950L,57951L,57952L,57953L,57954L,57955L,57956L,57957L,
94813 57958L,57959L,57960L,57961L,57962L,57963L,57964L,57965L,57966L,57967L,
94814 57968L,57969L,57970L,57971L,57972L,57973L,57974L,57975L,57976L,57977L,
94815 57978L,57979L,57980L,57981L,57982L,57983L,57984L,57985L,57986L,57987L,
94816 57988L,57989L,57990L,57991L,57992L,57993L,57994L,57995L,57996L,57997L,
94817 57998L,57999L,58000L,58001L,58002L,58003L,58004L,58005L,58006L,58007L,
94818 58008L,58009L,58010L,58011L,58012L,58013L,58014L,58015L,58016L,58017L,
94819 58018L,58019L,58020L,58021L,58022L,58023L,58024L,58025L,58026L,58027L,
94820 58028L,58029L,58030L,58031L,58032L,58033L,58034L,58035L,58036L,58037L,
94821 58038L,58039L,58040L,58041L,58042L,58043L,58044L,58045L,58046L,58047L,
94822 58048L,58049L,58050L,58051L,58052L,58053L,58054L,58055L,58056L,58057L,
94823 58058L,58059L,58060L,58061L,58062L,58063L,58064L,58065L,58066L,58067L,
94824 58068L,58069L,58070L,58071L,58072L,58073L,58074L,58075L,58076L,58077L,
94825 58078L,58079L,58080L,58081L,58082L,58083L,58084L,58085L,58086L,58087L,
94826 58088L,58089L,58090L,58091L,58092L,58093L,58094L,58095L,58096L,58097L,
94827 58098L,58099L,58100L,58101L,58102L,58103L,58104L,58105L,58106L,58107L,
94828 58108L,58109L,58110L,58111L,58112L,58113L,58114L,58115L,58116L,58117L,
94829 58118L,58119L,58120L,58121L,58122L,58123L,58124L,58125L,58126L,58127L,
94830 58128L,58129L,58130L,58131L,58132L,58133L,58134L,58135L,58136L,58137L,
94831 58138L,58139L,58140L,58141L,58142L,58143L,58144L,58145L,58146L,58147L,
94832 58148L,58149L,58150L,58151L,58152L,58153L,58154L,58155L,58156L,58157L,
94833 58158L,58159L,58160L,58161L,58162L,58163L,58164L,58165L,58166L,58167L,
94834 58168L,58169L,58170L,58171L,58172L,58173L,58174L,58175L,58176L,58177L,
94835 58178L,58179L,58180L,58181L,58182L,58183L,58184L,58185L,58186L,58187L,
94836 58188L,58189L,58190L,58191L,58192L,58193L,58194L,58195L,58196L,58197L,
94837 58198L,58199L,58200L,58201L,58202L,58203L,58204L,58205L,58206L,58207L,
94838 58208L,58209L,58210L,58211L,58212L,58213L,58214L,58215L,58216L,58217L,
94839 58218L,58219L,58220L,58221L,58222L,58223L,58224L,58225L,58226L,58227L,
94840 58228L,58229L,58230L,58231L,58232L,58233L,58234L,58235L,58236L,58237L,
94841 58238L,58239L,58240L,58241L,58242L,58243L,58244L,58245L,58246L,58247L,
94842 58248L,58249L,58250L,58251L,58252L,58253L,58254L,58255L,58256L,58257L,
94843 58258L,58259L,58260L,58261L,58262L,58263L,58264L,58265L,58266L,58267L,
94844 58268L,58269L,58270L,58271L,58272L,58273L,58274L,58275L,58276L,58277L,
94845 58278L,58279L,58280L,58281L,58282L,58283L,58284L,58285L,58286L,58287L,
94846 58288L,58289L,58290L,58291L,58292L,58293L,58294L,58295L,58296L,58297L,
94847 58298L,58299L,58300L,58301L,58302L,58303L,58304L,58305L,58306L,58307L,
94848 58308L,58309L,58310L,58311L,58312L,58313L,58314L,58315L,58316L,58317L,
94849 58318L,58319L,58320L,58321L,58322L,58323L,58324L,58325L,58326L,58327L,
94850 58328L,58329L,58330L,58331L,58332L,58333L,58334L,58335L,58336L,58337L,
94851 58338L,58339L,58340L,58341L,58342L,58343L,58344L,58345L,58346L,58347L,
94852 58348L,58349L,58350L,58351L,58352L,58353L,58354L,58355L,58356L,58357L,
94853 58358L,58359L,58360L,58361L,58362L,58363L,58364L,58365L,58366L,58367L,
94854 58368L,58369L,58370L,58371L,58372L,58373L,58374L,58375L,58376L,58377L,
94855 58378L,58379L,58380L,58381L,58382L,58383L,58384L,58385L,58386L,58387L,
94856 58388L,58389L,58390L,58391L,58392L,58393L,58394L,58395L,58396L,58397L,
94857 58398L,58399L,58400L,58401L,58402L,58403L,58404L,58405L,58406L,58407L,
94858 58408L,58409L,58410L,58411L,58412L,58413L,58414L,58415L,58416L,58417L,
94859 58418L,58419L,58420L,58421L,58422L,58423L,58424L,58425L,58426L,58427L,
94860 58428L,58429L,58430L,58431L,58432L,58433L,58434L,58435L,58436L,58437L,
94861 58438L,58439L,58440L,58441L,58442L,58443L,58444L,58445L,58446L,58447L,
94862 58448L,58449L,58450L,58451L,58452L,58453L,58454L,58455L,58456L,58457L,
94863 58458L,58459L,58460L,58461L,58462L,58463L,58464L,58465L,58466L,58467L,
94864 58468L,58469L,58470L,58471L,58472L,58473L,58474L,58475L,58476L,58477L,
94865 58478L,58479L,58480L,58481L,58482L,58483L,58484L,58485L,58486L,58487L,
94866 58488L,58489L,58490L,58491L,58492L,58493L,58494L,58495L,58496L,58497L,
94867 58498L,58499L,58500L,58501L,58502L,58503L,58504L,58505L,58506L,58507L,
94868 58508L,58509L,58510L,58511L,58512L,58513L,58514L,58515L,58516L,58517L,
94869 58518L,58519L,58520L,58521L,58522L,58523L,58524L,58525L,58526L,58527L,
94870 58528L,58529L,58530L,58531L,58532L,58533L,58534L,58535L,58536L,58537L,
94871 58538L,58539L,58540L,58541L,58542L,58543L,58544L,58545L,58546L,58547L,
94872 58548L,58549L,58550L,58551L,58552L,58553L,58554L,58555L,58556L,58557L,
94873 58558L,58559L,58560L,58561L,58562L,58563L,58564L,58565L,58566L,58567L,
94874 58568L,58569L,58570L,58571L,58572L,58573L,58574L,58575L,58576L,58577L,
94875 58578L,58579L,58580L,58581L,58582L,58583L,58584L,58585L,58586L,58587L,
94876 58588L,58589L,58590L,58591L,58592L,58593L,58594L,58595L,58596L,58597L,
94877 58598L,58599L,58600L,58601L,58602L,58603L,58604L,58605L,58606L,58607L,
94878 58608L,58609L,58610L,58611L,58612L,58613L,58614L,58615L,58616L,58617L,
94879 58618L,58619L,58620L,58621L,58622L,58623L,58624L,58625L,58626L,58627L,
94880 58628L,58629L,58630L,58631L,58632L,58633L,58634L,58635L,58636L,58637L,
94881 58638L,58639L,58640L,58641L,58642L,58643L,58644L,58645L,58646L,58647L,
94882 58648L,58649L,58650L,58651L,58652L,58653L,58654L,58655L,58656L,58657L,
94883 58658L,58659L,58660L,58661L,58662L,58663L,58664L,58665L,58666L,58667L,
94884 58668L,58669L,58670L,58671L,58672L,58673L,58674L,58675L,58676L,58677L,
94885 58678L,58679L,58680L,58681L,58682L,58683L,58684L,58685L,58686L,58687L,
94886 58688L,58689L,58690L,58691L,58692L,58693L,58694L,58695L,58696L,58697L,
94887 58698L,58699L,58700L,58701L,58702L,58703L,58704L,58705L,58706L,58707L,
94888 58708L,58709L,58710L,58711L,58712L,58713L,58714L,58715L,58716L,58717L,
94889 58718L,58719L,58720L,58721L,58722L,58723L,58724L,58725L,58726L,58727L,
94890 58728L,58729L,58730L,58731L,58732L,58733L,58734L,58735L,58736L,58737L,
94891 58738L,58739L,58740L,58741L,58742L,58743L,58744L,58745L,58746L,58747L,
94892 58748L,58749L,58750L,58751L,58752L,58753L,58754L,58755L,58756L,58757L,
94893 58758L,58759L,58760L,58761L,58762L,58763L,58764L,58765L,58766L,58767L,
94894 58768L,58769L,58770L,58771L,58772L,58773L,58774L,58775L,58776L,58777L,
94895 58778L,58779L,58780L,58781L,58782L,58783L,58784L,58785L,58786L,58787L,
94896 58788L,58789L,58790L,58791L,58792L,58793L,58794L,58795L,58796L,58797L,
94897 58798L,58799L,58800L,58801L,58802L,58803L,58804L,58805L,58806L,58807L,
94898 58808L,58809L,58810L,58811L,58812L,58813L,58814L,58815L,58816L,58817L,
94899 58818L,58819L,58820L,58821L,58822L,58823L,58824L,58825L,58826L,58827L,
94900 58828L,58829L,58830L,58831L,58832L,58833L,58834L,58835L,58836L,58837L,
94901 58838L,58839L,58840L,58841L,58842L,58843L,58844L,58845L,58846L,58847L,
94902 58848L,58849L,58850L,58851L,58852L,58853L,58854L,58855L,58856L,58857L,
94903 58858L,58859L,58860L,58861L,58862L,58863L,58864L,58865L,58866L,58867L,
94904 58868L,58869L,58870L,58871L,58872L,58873L,58874L,58875L,58876L,58877L,
94905 58878L,58879L,58880L,58881L,58882L,58883L,58884L,58885L,58886L,58887L,
94906 58888L,58889L,58890L,58891L,58892L,58893L,58894L,58895L,58896L,58897L,
94907 58898L,58899L,58900L,58901L,58902L,58903L,58904L,58905L,58906L,58907L,
94908 58908L,58909L,58910L,58911L,58912L,58913L,58914L,58915L,58916L,58917L,
94909 58918L,58919L,58920L,58921L,58922L,58923L,58924L,58925L,58926L,58927L,
94910 58928L,58929L,58930L,58931L,58932L,58933L,58934L,58935L,58936L,58937L,
94911 58938L,58939L,58940L,58941L,58942L,58943L,58944L,58945L,58946L,58947L,
94912 58948L,58949L,58950L,58951L,58952L,58953L,58954L,58955L,58956L,58957L,
94913 58958L,58959L,58960L,58961L,58962L,58963L,58964L,58965L,58966L,58967L,
94914 58968L,58969L,58970L,58971L,58972L,58973L,58974L,58975L,58976L,58977L,
94915 58978L,58979L,58980L,58981L,58982L,58983L,58984L,58985L,58986L,58987L,
94916 58988L,58989L,58990L,58991L,58992L,58993L,58994L,58995L,58996L,58997L,
94917 58998L,58999L,59000L,59001L,59002L,59003L,59004L,59005L,59006L,59007L,
94918 59008L,59009L,59010L,59011L,59012L,59013L,59014L,59015L,59016L,59017L,
94919 59018L,59019L,59020L,59021L,59022L,59023L,59024L,59025L,59026L,59027L,
94920 59028L,59029L,59030L,59031L,59032L,59033L,59034L,59035L,59036L,59037L,
94921 59038L,59039L,59040L,59041L,59042L,59043L,59044L,59045L,59046L,59047L,
94922 59048L,59049L,59050L,59051L,59052L,59053L,59054L,59055L,59056L,59057L,
94923 59058L,59059L,59060L,59061L,59062L,59063L,59064L,59065L,59066L,59067L,
94924 59068L,59069L,59070L,59071L,59072L,59073L,59074L,59075L,59076L,59077L,
94925 59078L,59079L,59080L,59081L,59082L,59083L,59084L,59085L,59086L,59087L,
94926 59088L,59089L,59090L,59091L,59092L,59093L,59094L,59095L,59096L,59097L,
94927 59098L,59099L,59100L,59101L,59102L,59103L,59104L,59105L,59106L,59107L,
94928 59108L,59109L,59110L,59111L,59112L,59113L,59114L,59115L,59116L,59117L,
94929 59118L,59119L,59120L,59121L,59122L,59123L,59124L,59125L,59126L,59127L,
94930 59128L,59129L,59130L,59131L,59132L,59133L,59134L,59135L,59136L,59137L,
94931 59138L,59139L,59140L,59141L,59142L,59143L,59144L,59145L,59146L,59147L,
94932 59148L,59149L,59150L,59151L,59152L,59153L,59154L,59155L,59156L,59157L,
94933 59158L,59159L,59160L,59161L,59162L,59163L,59164L,59165L,59166L,59167L,
94934 59168L,59169L,59170L,59171L,59172L,59173L,59174L,59175L,59176L,59177L,
94935 59178L,59179L,59180L,59181L,59182L,59183L,59184L,59185L,59186L,59187L,
94936 59188L,59189L,59190L,59191L,59192L,59193L,59194L,59195L,59196L,59197L,
94937 59198L,59199L,59200L,59201L,59202L,59203L,59204L,59205L,59206L,59207L,
94938 59208L,59209L,59210L,59211L,59212L,59213L,59214L,59215L,59216L,59217L,
94939 59218L,59219L,59220L,59221L,59222L,59223L,59224L,59225L,59226L,59227L,
94940 59228L,59229L,59230L,59231L,59232L,59233L,59234L,59235L,59236L,59237L,
94941 59238L,59239L,59240L,59241L,59242L,59243L,59244L,59245L,59246L,59247L,
94942 59248L,59249L,59250L,59251L,59252L,59253L,59254L,59255L,59256L,59257L,
94943 59258L,59259L,59260L,59261L,59262L,59263L,59264L,59265L,59266L,59267L,
94944 59268L,59269L,59270L,59271L,59272L,59273L,59274L,59275L,59276L,59277L,
94945 59278L,59279L,59280L,59281L,59282L,59283L,59284L,59285L,59286L,59287L,
94946 59288L,59289L,59290L,59291L,59292L,59293L,59294L,59295L,59296L,59297L,
94947 59298L,59299L,59300L,59301L,59302L,59303L,59304L,59305L,59306L,59307L,
94948 59308L,59309L,59310L,59311L,59312L,59313L,59314L,59315L,59316L,59317L,
94949 59318L,59319L,59320L,59321L,59322L,59323L,59324L,59325L,59326L,59327L,
94950 59328L,59329L,59330L,59331L,59332L,59333L,59334L,59335L,59336L,59337L,
94951 59338L,59339L,59340L,59341L,59342L,59343L,59344L,59345L,59346L,59347L,
94952 59348L,59349L,59350L,59351L,59352L,59353L,59354L,59355L,59356L,59357L,
94953 59358L,59359L,59360L,59361L,59362L,59363L,59364L,59365L,59366L,59367L,
94954 59368L,59369L,59370L,59371L,59372L,59373L,59374L,59375L,59376L,59377L,
94955 59378L,59379L,59380L,59381L,59382L,59383L,59384L,59385L,59386L,59387L,
94956 59388L,59389L,59390L,59391L,59392L,59393L,59394L,59395L,59396L,59397L,
94957 59398L,59399L,59400L,59401L,59402L,59403L,59404L,59405L,59406L,59407L,
94958 59408L,59409L,59410L,59411L,59412L,59413L,59414L,59415L,59416L,59417L,
94959 59418L,59419L,59420L,59421L,59422L,59423L,59424L,59425L,59426L,59427L,
94960 59428L,59429L,59430L,59431L,59432L,59433L,59434L,59435L,59436L,59437L,
94961 59438L,59439L,59440L,59441L,59442L,59443L,59444L,59445L,59446L,59447L,
94962 59448L,59449L,59450L,59451L,59452L,59453L,59454L,59455L,59456L,59457L,
94963 59458L,59459L,59460L,59461L,59462L,59463L,59464L,59465L,59466L,59467L,
94964 59468L,59469L,59470L,59471L,59472L,59473L,59474L,59475L,59476L,59477L,
94965 59478L,59479L,59480L,59481L,59482L,59483L,59484L,59485L,59486L,59487L,
94966 59488L,59489L,59490L,59491L,59492L,59493L,59494L,59495L,59496L,59497L,
94967 59498L,59499L,59500L,59501L,59502L,59503L,59504L,59505L,59506L,59507L,
94968 59508L,59509L,59510L,59511L,59512L,59513L,59514L,59515L,59516L,59517L,
94969 59518L,59519L,59520L,59521L,59522L,59523L,59524L,59525L,59526L,59527L,
94970 59528L,59529L,59530L,59531L,59532L,59533L,59534L,59535L,59536L,59537L,
94971 59538L,59539L,59540L,59541L,59542L,59543L,59544L,59545L,59546L,59547L,
94972 59548L,59549L,59550L,59551L,59552L,59553L,59554L,59555L,59556L,59557L,
94973 59558L,59559L,59560L,59561L,59562L,59563L,59564L,59565L,59566L,59567L,
94974 59568L,59569L,59570L,59571L,59572L,59573L,59574L,59575L,59576L,59577L,
94975 59578L,59579L,59580L,59581L,59582L,59583L,59584L,59585L,59586L,59587L,
94976 59588L,59589L,59590L,59591L,59592L,59593L,59594L,59595L,59596L,59597L,
94977 59598L,59599L,59600L,59601L,59602L,59603L,59604L,59605L,59606L,59607L,
94978 59608L,59609L,59610L,59611L,59612L,59613L,59614L,59615L,59616L,59617L,
94979 59618L,59619L,59620L,59621L,59622L,59623L,59624L,59625L,59626L,59627L,
94980 59628L,59629L,59630L,59631L,59632L,59633L,59634L,59635L,59636L,59637L,
94981 59638L,59639L,59640L,59641L,59642L,59643L,59644L,59645L,59646L,59647L,
94982 59648L,59649L,59650L,59651L,59652L,59653L,59654L,59655L,59656L,59657L,
94983 59658L,59659L,59660L,59661L,59662L,59663L,59664L,59665L,59666L,59667L,
94984 59668L,59669L,59670L,59671L,59672L,59673L,59674L,59675L,59676L,59677L,
94985 59678L,59679L,59680L,59681L,59682L,59683L,59684L,59685L,59686L,59687L,
94986 59688L,59689L,59690L,59691L,59692L,59693L,59694L,59695L,59696L,59697L,
94987 59698L,59699L,59700L,59701L,59702L,59703L,59704L,59705L,59706L,59707L,
94988 59708L,59709L,59710L,59711L,59712L,59713L,59714L,59715L,59716L,59717L,
94989 59718L,59719L,59720L,59721L,59722L,59723L,59724L,59725L,59726L,59727L,
94990 59728L,59729L,59730L,59731L,59732L,59733L,59734L,59735L,59736L,59737L,
94991 59738L,59739L,59740L,59741L,59742L,59743L,59744L,59745L,59746L,59747L,
94992 59748L,59749L,59750L,59751L,59752L,59753L,59754L,59755L,59756L,59757L,
94993 59758L,59759L,59760L,59761L,59762L,59763L,59764L,59765L,59766L,59767L,
94994 59768L,59769L,59770L,59771L,59772L,59773L,59774L,59775L,59776L,59777L,
94995 59778L,59779L,59780L,59781L,59782L,59783L,59784L,59785L,59786L,59787L,
94996 59788L,59789L,59790L,59791L,59792L,59793L,59794L,59795L,59796L,59797L,
94997 59798L,59799L,59800L,59801L,59802L,59803L,59804L,59805L,59806L,59807L,
94998 59808L,59809L,59810L,59811L,59812L,59813L,59814L,59815L,59816L,59817L,
94999 59818L,59819L,59820L,59821L,59822L,59823L,59824L,59825L,59826L,59827L,
95000 59828L,59829L,59830L,59831L,59832L,59833L,59834L,59835L,59836L,59837L,
95001 59838L,59839L,59840L,59841L,59842L,59843L,59844L,59845L,59846L,59847L,
95002 59848L,59849L,59850L,59851L,59852L,59853L,59854L,59855L,59856L,59857L,
95003 59858L,59859L,59860L,59861L,59862L,59863L,59864L,59865L,59866L,59867L,
95004 59868L,59869L,59870L,59871L,59872L,59873L,59874L,59875L,59876L,59877L,
95005 59878L,59879L,59880L,59881L,59882L,59883L,59884L,59885L,59886L,59887L,
95006 59888L,59889L,59890L,59891L,59892L,59893L,59894L,59895L,59896L,59897L,
95007 59898L,59899L,59900L,59901L,59902L,59903L,59904L,59905L,59906L,59907L,
95008 59908L,59909L,59910L,59911L,59912L,59913L,59914L,59915L,59916L,59917L,
95009 59918L,59919L,59920L,59921L,59922L,59923L,59924L,59925L,59926L,59927L,
95010 59928L,59929L,59930L,59931L,59932L,59933L,59934L,59935L,59936L,59937L,
95011 59938L,59939L,59940L,59941L,59942L,59943L,59944L,59945L,59946L,59947L,
95012 59948L,59949L,59950L,59951L,59952L,59953L,59954L,59955L,59956L,59957L,
95013 59958L,59959L,59960L,59961L,59962L,59963L,59964L,59965L,59966L,59967L,
95014 59968L,59969L,59970L,59971L,59972L,59973L,59974L,59975L,59976L,59977L,
95015 59978L,59979L,59980L,59981L,59982L,59983L,59984L,59985L,59986L,59987L,
95016 59988L,59989L,59990L,59991L,59992L,59993L,59994L,59995L,59996L,59997L,
95017 59998L,59999L,60000L,60001L,60002L,60003L,60004L,60005L,60006L,60007L,
95018 60008L,60009L,60010L,60011L,60012L,60013L,60014L,60015L,60016L,60017L,
95019 60018L,60019L,60020L,60021L,60022L,60023L,60024L,60025L,60026L,60027L,
95020 60028L,60029L,60030L,60031L,60032L,60033L,60034L,60035L,60036L,60037L,
95021 60038L,60039L,60040L,60041L,60042L,60043L,60044L,60045L,60046L,60047L,
95022 60048L,60049L,60050L,60051L,60052L,60053L,60054L,60055L,60056L,60057L,
95023 60058L,60059L,60060L,60061L,60062L,60063L,60064L,60065L,60066L,60067L,
95024 60068L,60069L,60070L,60071L,60072L,60073L,60074L,60075L,60076L,60077L,
95025 60078L,60079L,60080L,60081L,60082L,60083L,60084L,60085L,60086L,60087L,
95026 60088L,60089L,60090L,60091L,60092L,60093L,60094L,60095L,60096L,60097L,
95027 60098L,60099L,60100L,60101L,60102L,60103L,60104L,60105L,60106L,60107L,
95028 60108L,60109L,60110L,60111L,60112L,60113L,60114L,60115L,60116L,60117L,
95029 60118L,60119L,60120L,60121L,60122L,60123L,60124L,60125L,60126L,60127L,
95030 60128L,60129L,60130L,60131L,60132L,60133L,60134L,60135L,60136L,60137L,
95031 60138L,60139L,60140L,60141L,60142L,60143L,60144L,60145L,60146L,60147L,
95032 60148L,60149L,60150L,60151L,60152L,60153L,60154L,60155L,60156L,60157L,
95033 60158L,60159L,60160L,60161L,60162L,60163L,60164L,60165L,60166L,60167L,
95034 60168L,60169L,60170L,60171L,60172L,60173L,60174L,60175L,60176L,60177L,
95035 60178L,60179L,60180L,60181L,60182L,60183L,60184L,60185L,60186L,60187L,
95036 60188L,60189L,60190L,60191L,60192L,60193L,60194L,60195L,60196L,60197L,
95037 60198L,60199L,60200L,60201L,60202L,60203L,60204L,60205L,60206L,60207L,
95038 60208L,60209L,60210L,60211L,60212L,60213L,60214L,60215L,60216L,60217L,
95039 60218L,60219L,60220L,60221L,60222L,60223L,60224L,60225L,60226L,60227L,
95040 60228L,60229L,60230L,60231L,60232L,60233L,60234L,60235L,60236L,60237L,
95041 60238L,60239L,60240L,60241L,60242L,60243L,60244L,60245L,60246L,60247L,
95042 60248L,60249L,60250L,60251L,60252L,60253L,60254L,60255L,60256L,60257L,
95043 60258L,60259L,60260L,60261L,60262L,60263L,60264L,60265L,60266L,60267L,
95044 60268L,60269L,60270L,60271L,60272L,60273L,60274L,60275L,60276L,60277L,
95045 60278L,60279L,60280L,60281L,60282L,60283L,60284L,60285L,60286L,60287L,
95046 60288L,60289L,60290L,60291L,60292L,60293L,60294L,60295L,60296L,60297L,
95047 60298L,60299L,60300L,60301L,60302L,60303L,60304L,60305L,60306L,60307L,
95048 60308L,60309L,60310L,60311L,60312L,60313L,60314L,60315L,60316L,60317L,
95049 60318L,60319L,60320L,60321L,60322L,60323L,60324L,60325L,60326L,60327L,
95050 60328L,60329L,60330L,60331L,60332L,60333L,60334L,60335L,60336L,60337L,
95051 60338L,60339L,60340L,60341L,60342L,60343L,60344L,60345L,60346L,60347L,
95052 60348L,60349L,60350L,60351L,60352L,60353L,60354L,60355L,60356L,60357L,
95053 60358L,60359L,60360L,60361L,60362L,60363L,60364L,60365L,60366L,60367L,
95054 60368L,60369L,60370L,60371L,60372L,60373L,60374L,60375L,60376L,60377L,
95055 60378L,60379L,60380L,60381L,60382L,60383L,60384L,60385L,60386L,60387L,
95056 60388L,60389L,60390L,60391L,60392L,60393L,60394L,60395L,60396L,60397L,
95057 60398L,60399L,60400L,60401L,60402L,60403L,60404L,60405L,60406L,60407L,
95058 60408L,60409L,60410L,60411L,60412L,60413L,60414L,60415L,60416L,60417L,
95059 60418L,60419L,60420L,60421L,60422L,60423L,60424L,60425L,60426L,60427L,
95060 60428L,60429L,60430L,60431L,60432L,60433L,60434L,60435L,60436L,60437L,
95061 60438L,60439L,60440L,60441L,60442L,60443L,60444L,60445L,60446L,60447L,
95062 60448L,60449L,60450L,60451L,60452L,60453L,60454L,60455L,60456L,60457L,
95063 60458L,60459L,60460L,60461L,60462L,60463L,60464L,60465L,60466L,60467L,
95064 60468L,60469L,60470L,60471L,60472L,60473L,60474L,60475L,60476L,60477L,
95065 60478L,60479L,60480L,60481L,60482L,60483L,60484L,60485L,60486L,60487L,
95066 60488L,60489L,60490L,60491L,60492L,60493L,60494L,60495L,60496L,60497L,
95067 60498L,60499L,60500L,60501L,60502L,60503L,60504L,60505L,60506L,60507L,
95068 60508L,60509L,60510L,60511L,60512L,60513L,60514L,60515L,60516L,60517L,
95069 60518L,60519L,60520L,60521L,60522L,60523L,60524L,60525L,60526L,60527L,
95070 60528L,60529L,60530L,60531L,60532L,60533L,60534L,60535L,60536L,60537L,
95071 60538L,60539L,60540L,60541L,60542L,60543L,60544L,60545L,60546L,60547L,
95072 60548L,60549L,60550L,60551L,60552L,60553L,60554L,60555L,60556L,60557L,
95073 60558L,60559L,60560L,60561L,60562L,60563L,60564L,60565L,60566L,60567L,
95074 60568L,60569L,60570L,60571L,60572L,60573L,60574L,60575L,60576L,60577L,
95075 60578L,60579L,60580L,60581L,60582L,60583L,60584L,60585L,60586L,60587L,
95076 60588L,60589L,60590L,60591L,60592L,60593L,60594L,60595L,60596L,60597L,
95077 60598L,60599L,60600L,60601L,60602L,60603L,60604L,60605L,60606L,60607L,
95078 60608L,60609L,60610L,60611L,60612L,60613L,60614L,60615L,60616L,60617L,
95079 60618L,60619L,60620L,60621L,60622L,60623L,60624L,60625L,60626L,60627L,
95080 60628L,60629L,60630L,60631L,60632L,60633L,60634L,60635L,60636L,60637L,
95081 60638L,60639L,60640L,60641L,60642L,60643L,60644L,60645L,60646L,60647L,
95082 60648L,60649L,60650L,60651L,60652L,60653L,60654L,60655L,60656L,60657L,
95083 60658L,60659L,60660L,60661L,60662L,60663L,60664L,60665L,60666L,60667L,
95084 60668L,60669L,60670L,60671L,60672L,60673L,60674L,60675L,60676L,60677L,
95085 60678L,60679L,60680L,60681L,60682L,60683L,60684L,60685L,60686L,60687L,
95086 60688L,60689L,60690L,60691L,60692L,60693L,60694L,60695L,60696L,60697L,
95087 60698L,60699L,60700L,60701L,60702L,60703L,60704L,60705L,60706L,60707L,
95088 60708L,60709L,60710L,60711L,60712L,60713L,60714L,60715L,60716L,60717L,
95089 60718L,60719L,60720L,60721L,60722L,60723L,60724L,60725L,60726L,60727L,
95090 60728L,60729L,60730L,60731L,60732L,60733L,60734L,60735L,60736L,60737L,
95091 60738L,60739L,60740L,60741L,60742L,60743L,60744L,60745L,60746L,60747L,
95092 60748L,60749L,60750L,60751L,60752L,60753L,60754L,60755L,60756L,60757L,
95093 60758L,60759L,60760L,60761L,60762L,60763L,60764L,60765L,60766L,60767L,
95094 60768L,60769L,60770L,60771L,60772L,60773L,60774L,60775L,60776L,60777L,
95095 60778L,60779L,60780L,60781L,60782L,60783L,60784L,60785L,60786L,60787L,
95096 60788L,60789L,60790L,60791L,60792L,60793L,60794L,60795L,60796L,60797L,
95097 60798L,60799L,60800L,60801L,60802L,60803L,60804L,60805L,60806L,60807L,
95098 60808L,60809L,60810L,60811L,60812L,60813L,60814L,60815L,60816L,60817L,
95099 60818L,60819L,60820L,60821L,60822L,60823L,60824L,60825L,60826L,60827L,
95100 60828L,60829L,60830L,60831L,60832L,60833L,60834L,60835L,60836L,60837L,
95101 60838L,60839L,60840L,60841L,60842L,60843L,60844L,60845L,60846L,60847L,
95102 60848L,60849L,60850L,60851L,60852L,60853L,60854L,60855L,60856L,60857L,
95103 60858L,60859L,60860L,60861L,60862L,60863L,60864L,60865L,60866L,60867L,
95104 60868L,60869L,60870L,60871L,60872L,60873L,60874L,60875L,60876L,60877L,
95105 60878L,60879L,60880L,60881L,60882L,60883L,60884L,60885L,60886L,60887L,
95106 60888L,60889L,60890L,60891L,60892L,60893L,60894L,60895L,60896L,60897L,
95107 60898L,60899L,60900L,60901L,60902L,60903L,60904L,60905L,60906L,60907L,
95108 60908L,60909L,60910L,60911L,60912L,60913L,60914L,60915L,60916L,60917L,
95109 60918L,60919L,60920L,60921L,60922L,60923L,60924L,60925L,60926L,60927L,
95110 60928L,60929L,60930L,60931L,60932L,60933L,60934L,60935L,60936L,60937L,
95111 60938L,60939L,60940L,60941L,60942L,60943L,60944L,60945L,60946L,60947L,
95112 60948L,60949L,60950L,60951L,60952L,60953L,60954L,60955L,60956L,60957L,
95113 60958L,60959L,60960L,60961L,60962L,60963L,60964L,60965L,60966L,60967L,
95114 60968L,60969L,60970L,60971L,60972L,60973L,60974L,60975L,60976L,60977L,
95115 60978L,60979L,60980L,60981L,60982L,60983L,60984L,60985L,60986L,60987L,
95116 60988L,60989L,60990L,60991L,60992L,60993L,60994L,60995L,60996L,60997L,
95117 60998L,60999L,61000L,61001L,61002L,61003L,61004L,61005L,61006L,61007L,
95118 61008L,61009L,61010L,61011L,61012L,61013L,61014L,61015L,61016L,61017L,
95119 61018L,61019L,61020L,61021L,61022L,61023L,61024L,61025L,61026L,61027L,
95120 61028L,61029L,61030L,61031L,61032L,61033L,61034L,61035L,61036L,61037L,
95121 61038L,61039L,61040L,61041L,61042L,61043L,61044L,61045L,61046L,61047L,
95122 61048L,61049L,61050L,61051L,61052L,61053L,61054L,61055L,61056L,61057L,
95123 61058L,61059L,61060L,61061L,61062L,61063L,61064L,61065L,61066L,61067L,
95124 61068L,61069L,61070L,61071L,61072L,61073L,61074L,61075L,61076L,61077L,
95125 61078L,61079L,61080L,61081L,61082L,61083L,61084L,61085L,61086L,61087L,
95126 61088L,61089L,61090L,61091L,61092L,61093L,61094L,61095L,61096L,61097L,
95127 61098L,61099L,61100L,61101L,61102L,61103L,61104L,61105L,61106L,61107L,
95128 61108L,61109L,61110L,61111L,61112L,61113L,61114L,61115L,61116L,61117L,
95129 61118L,61119L,61120L,61121L,61122L,61123L,61124L,61125L,61126L,61127L,
95130 61128L,61129L,61130L,61131L,61132L,61133L,61134L,61135L,61136L,61137L,
95131 61138L,61139L,61140L,61141L,61142L,61143L,61144L,61145L,61146L,61147L,
95132 61148L,61149L,61150L,61151L,61152L,61153L,61154L,61155L,61156L,61157L,
95133 61158L,61159L,61160L,61161L,61162L,61163L,61164L,61165L,61166L,61167L,
95134 61168L,61169L,61170L,61171L,61172L,61173L,61174L,61175L,61176L,61177L,
95135 61178L,61179L,61180L,61181L,61182L,61183L,61184L,61185L,61186L,61187L,
95136 61188L,61189L,61190L,61191L,61192L,61193L,61194L,61195L,61196L,61197L,
95137 61198L,61199L,61200L,61201L,61202L,61203L,61204L,61205L,61206L,61207L,
95138 61208L,61209L,61210L,61211L,61212L,61213L,61214L,61215L,61216L,61217L,
95139 61218L,61219L,61220L,61221L,61222L,61223L,61224L,61225L,61226L,61227L,
95140 61228L,61229L,61230L,61231L,61232L,61233L,61234L,61235L,61236L,61237L,
95141 61238L,61239L,61240L,61241L,61242L,61243L,61244L,61245L,61246L,61247L,
95142 61248L,61249L,61250L,61251L,61252L,61253L,61254L,61255L,61256L,61257L,
95143 61258L,61259L,61260L,61261L,61262L,61263L,61264L,61265L,61266L,61267L,
95144 61268L,61269L,61270L,61271L,61272L,61273L,61274L,61275L,61276L,61277L,
95145 61278L,61279L,61280L,61281L,61282L,61283L,61284L,61285L,61286L,61287L,
95146 61288L,61289L,61290L,61291L,61292L,61293L,61294L,61295L,61296L,61297L,
95147 61298L,61299L,61300L,61301L,61302L,61303L,61304L,61305L,61306L,61307L,
95148 61308L,61309L,61310L,61311L,61312L,61313L,61314L,61315L,61316L,61317L,
95149 61318L,61319L,61320L,61321L,61322L,61323L,61324L,61325L,61326L,61327L,
95150 61328L,61329L,61330L,61331L,61332L,61333L,61334L,61335L,61336L,61337L,
95151 61338L,61339L,61340L,61341L,61342L,61343L,61344L,61345L,61346L,61347L,
95152 61348L,61349L,61350L,61351L,61352L,61353L,61354L,61355L,61356L,61357L,
95153 61358L,61359L,61360L,61361L,61362L,61363L,61364L,61365L,61366L,61367L,
95154 61368L,61369L,61370L,61371L,61372L,61373L,61374L,61375L,61376L,61377L,
95155 61378L,61379L,61380L,61381L,61382L,61383L,61384L,61385L,61386L,61387L,
95156 61388L,61389L,61390L,61391L,61392L,61393L,61394L,61395L,61396L,61397L,
95157 61398L,61399L,61400L,61401L,61402L,61403L,61404L,61405L,61406L,61407L,
95158 61408L,61409L,61410L,61411L,61412L,61413L,61414L,61415L,61416L,61417L,
95159 61418L,61419L,61420L,61421L,61422L,61423L,61424L,61425L,61426L,61427L,
95160 61428L,61429L,61430L,61431L,61432L,61433L,61434L,61435L,61436L,61437L,
95161 61438L,61439L,61440L,61441L,61442L,61443L,61444L,61445L,61446L,61447L,
95162 61448L,61449L,61450L,61451L,61452L,61453L,61454L,61455L,61456L,61457L,
95163 61458L,61459L,61460L,61461L,61462L,61463L,61464L,61465L,61466L,61467L,
95164 61468L,61469L,61470L,61471L,61472L,61473L,61474L,61475L,61476L,61477L,
95165 61478L,61479L,61480L,61481L,61482L,61483L,61484L,61485L,61486L,61487L,
95166 61488L,61489L,61490L,61491L,61492L,61493L,61494L,61495L,61496L,61497L,
95167 61498L,61499L,61500L,61501L,61502L,61503L,61504L,61505L,61506L,61507L,
95168 61508L,61509L,61510L,61511L,61512L,61513L,61514L,61515L,61516L,61517L,
95169 61518L,61519L,61520L,61521L,61522L,61523L,61524L,61525L,61526L,61527L,
95170 61528L,61529L,61530L,61531L,61532L,61533L,61534L,61535L,61536L,61537L,
95171 61538L,61539L,61540L,61541L,61542L,61543L,61544L,61545L,61546L,61547L,
95172 61548L,61549L,61550L,61551L,61552L,61553L,61554L,61555L,61556L,61557L,
95173 61558L,61559L,61560L,61561L,61562L,61563L,61564L,61565L,61566L,61567L,
95174 61568L,61569L,61570L,61571L,61572L,61573L,61574L,61575L,61576L,61577L,
95175 61578L,61579L,61580L,61581L,61582L,61583L,61584L,61585L,61586L,61587L,
95176 61588L,61589L,61590L,61591L,61592L,61593L,61594L,61595L,61596L,61597L,
95177 61598L,61599L,61600L,61601L,61602L,61603L,61604L,61605L,61606L,61607L,
95178 61608L,61609L,61610L,61611L,61612L,61613L,61614L,61615L,61616L,61617L,
95179 61618L,61619L,61620L,61621L,61622L,61623L,61624L,61625L,61626L,61627L,
95180 61628L,61629L,61630L,61631L,61632L,61633L,61634L,61635L,61636L,61637L,
95181 61638L,61639L,61640L,61641L,61642L,61643L,61644L,61645L,61646L,61647L,
95182 61648L,61649L,61650L,61651L,61652L,61653L,61654L,61655L,61656L,61657L,
95183 61658L,61659L,61660L,61661L,61662L,61663L,61664L,61665L,61666L,61667L,
95184 61668L,61669L,61670L,61671L,61672L,61673L,61674L,61675L,61676L,61677L,
95185 61678L,61679L,61680L,61681L,61682L,61683L,61684L,61685L,61686L,61687L,
95186 61688L,61689L,61690L,61691L,61692L,61693L,61694L,61695L,61696L,61697L,
95187 61698L,61699L,61700L,61701L,61702L,61703L,61704L,61705L,61706L,61707L,
95188 61708L,61709L,61710L,61711L,61712L,61713L,61714L,61715L,61716L,61717L,
95189 61718L,61719L,61720L,61721L,61722L,61723L,61724L,61725L,61726L,61727L,
95190 61728L,61729L,61730L,61731L,61732L,61733L,61734L,61735L,61736L,61737L,
95191 61738L,61739L,61740L,61741L,61742L,61743L,61744L,61745L,61746L,61747L,
95192 61748L,61749L,61750L,61751L,61752L,61753L,61754L,61755L,61756L,61757L,
95193 61758L,61759L,61760L,61761L,61762L,61763L,61764L,61765L,61766L,61767L,
95194 61768L,61769L,61770L,61771L,61772L,61773L,61774L,61775L,61776L,61777L,
95195 61778L,61779L,61780L,61781L,61782L,61783L,61784L,61785L,61786L,61787L,
95196 61788L,61789L,61790L,61791L,61792L,61793L,61794L,61795L,61796L,61797L,
95197 61798L,61799L,61800L,61801L,61802L,61803L,61804L,61805L,61806L,61807L,
95198 61808L,61809L,61810L,61811L,61812L,61813L,61814L,61815L,61816L,61817L,
95199 61818L,61819L,61820L,61821L,61822L,61823L,61824L,61825L,61826L,61827L,
95200 61828L,61829L,61830L,61831L,61832L,61833L,61834L,61835L,61836L,61837L,
95201 61838L,61839L,61840L,61841L,61842L,61843L,61844L,61845L,61846L,61847L,
95202 61848L,61849L,61850L,61851L,61852L,61853L,61854L,61855L,61856L,61857L,
95203 61858L,61859L,61860L,61861L,61862L,61863L,61864L,61865L,61866L,61867L,
95204 61868L,61869L,61870L,61871L,61872L,61873L,61874L,61875L,61876L,61877L,
95205 61878L,61879L,61880L,61881L,61882L,61883L,61884L,61885L,61886L,61887L,
95206 61888L,61889L,61890L,61891L,61892L,61893L,61894L,61895L,61896L,61897L,
95207 61898L,61899L,61900L,61901L,61902L,61903L,61904L,61905L,61906L,61907L,
95208 61908L,61909L,61910L,61911L,61912L,61913L,61914L,61915L,61916L,61917L,
95209 61918L,61919L,61920L,61921L,61922L,61923L,61924L,61925L,61926L,61927L,
95210 61928L,61929L,61930L,61931L,61932L,61933L,61934L,61935L,61936L,61937L,
95211 61938L,61939L,61940L,61941L,61942L,61943L,61944L,61945L,61946L,61947L,
95212 61948L,61949L,61950L,61951L,61952L,61953L,61954L,61955L,61956L,61957L,
95213 61958L,61959L,61960L,61961L,61962L,61963L,61964L,61965L,61966L,61967L,
95214 61968L,61969L,61970L,61971L,61972L,61973L,61974L,61975L,61976L,61977L,
95215 61978L,61979L,61980L,61981L,61982L,61983L,61984L,61985L,61986L,61987L,
95216 61988L,61989L,61990L,61991L,61992L,61993L,61994L,61995L,61996L,61997L,
95217 61998L,61999L,62000L,62001L,62002L,62003L,62004L,62005L,62006L,62007L,
95218 62008L,62009L,62010L,62011L,62012L,62013L,62014L,62015L,62016L,62017L,
95219 62018L,62019L,62020L,62021L,62022L,62023L,62024L,62025L,62026L,62027L,
95220 62028L,62029L,62030L,62031L,62032L,62033L,62034L,62035L,62036L,62037L,
95221 62038L,62039L,62040L,62041L,62042L,62043L,62044L,62045L,62046L,62047L,
95222 62048L,62049L,62050L,62051L,62052L,62053L,62054L,62055L,62056L,62057L,
95223 62058L,62059L,62060L,62061L,62062L,62063L,62064L,62065L,62066L,62067L,
95224 62068L,62069L,62070L,62071L,62072L,62073L,62074L,62075L,62076L,62077L,
95225 62078L,62079L,62080L,62081L,62082L,62083L,62084L,62085L,62086L,62087L,
95226 62088L,62089L,62090L,62091L,62092L,62093L,62094L,62095L,62096L,62097L,
95227 62098L,62099L,62100L,62101L,62102L,62103L,62104L,62105L,62106L,62107L,
95228 62108L,62109L,62110L,62111L,62112L,62113L,62114L,62115L,62116L,62117L,
95229 62118L,62119L,62120L,62121L,62122L,62123L,62124L,62125L,62126L,62127L,
95230 62128L,62129L,62130L,62131L,62132L,62133L,62134L,62135L,62136L,62137L,
95231 62138L,62139L,62140L,62141L,62142L,62143L,62144L,62145L,62146L,62147L,
95232 62148L,62149L,62150L,62151L,62152L,62153L,62154L,62155L,62156L,62157L,
95233 62158L,62159L,62160L,62161L,62162L,62163L,62164L,62165L,62166L,62167L,
95234 62168L,62169L,62170L,62171L,62172L,62173L,62174L,62175L,62176L,62177L,
95235 62178L,62179L,62180L,62181L,62182L,62183L,62184L,62185L,62186L,62187L,
95236 62188L,62189L,62190L,62191L,62192L,62193L,62194L,62195L,62196L,62197L,
95237 62198L,62199L,62200L,62201L,62202L,62203L,62204L,62205L,62206L,62207L,
95238 62208L,62209L,62210L,62211L,62212L,62213L,62214L,62215L,62216L,62217L,
95239 62218L,62219L,62220L,62221L,62222L,62223L,62224L,62225L,62226L,62227L,
95240 62228L,62229L,62230L,62231L,62232L,62233L,62234L,62235L,62236L,62237L,
95241 62238L,62239L,62240L,62241L,62242L,62243L,62244L,62245L,62246L,62247L,
95242 62248L,62249L,62250L,62251L,62252L,62253L,62254L,62255L,62256L,62257L,
95243 62258L,62259L,62260L,62261L,62262L,62263L,62264L,62265L,62266L,62267L,
95244 62268L,62269L,62270L,62271L,62272L,62273L,62274L,62275L,62276L,62277L,
95245 62278L,62279L,62280L,62281L,62282L,62283L,62284L,62285L,62286L,62287L,
95246 62288L,62289L,62290L,62291L,62292L,62293L,62294L,62295L,62296L,62297L,
95247 62298L,62299L,62300L,62301L,62302L,62303L,62304L,62305L,62306L,62307L,
95248 62308L,62309L,62310L,62311L,62312L,62313L,62314L,62315L,62316L,62317L,
95249 62318L,62319L,62320L,62321L,62322L,62323L,62324L,62325L,62326L,62327L,
95250 62328L,62329L,62330L,62331L,62332L,62333L,62334L,62335L,62336L,62337L,
95251 62338L,62339L,62340L,62341L,62342L,62343L,62344L,62345L,62346L,62347L,
95252 62348L,62349L,62350L,62351L,62352L,62353L,62354L,62355L,62356L,62357L,
95253 62358L,62359L,62360L,62361L,62362L,62363L,62364L,62365L,62366L,62367L,
95254 62368L,62369L,62370L,62371L,62372L,62373L,62374L,62375L,62376L,62377L,
95255 62378L,62379L,62380L,62381L,62382L,62383L,62384L,62385L,62386L,62387L,
95256 62388L,62389L,62390L,62391L,62392L,62393L,62394L,62395L,62396L,62397L,
95257 62398L,62399L,62400L,62401L,62402L,62403L,62404L,62405L,62406L,62407L,
95258 62408L,62409L,62410L,62411L,62412L,62413L,62414L,62415L,62416L,62417L,
95259 62418L,62419L,62420L,62421L,62422L,62423L,62424L,62425L,62426L,62427L,
95260 62428L,62429L,62430L,62431L,62432L,62433L,62434L,62435L,62436L,62437L,
95261 62438L,62439L,62440L,62441L,62442L,62443L,62444L,62445L,62446L,62447L,
95262 62448L,62449L,62450L,62451L,62452L,62453L,62454L,62455L,62456L,62457L,
95263 62458L,62459L,62460L,62461L,62462L,62463L,62464L,62465L,62466L,62467L,
95264 62468L,62469L,62470L,62471L,62472L,62473L,62474L,62475L,62476L,62477L,
95265 62478L,62479L,62480L,62481L,62482L,62483L,62484L,62485L,62486L,62487L,
95266 62488L,62489L,62490L,62491L,62492L,62493L,62494L,62495L,62496L,62497L,
95267 62498L,62499L,62500L,62501L,62502L,62503L,62504L,62505L,62506L,62507L,
95268 62508L,62509L,62510L,62511L,62512L,62513L,62514L,62515L,62516L,62517L,
95269 62518L,62519L,62520L,62521L,62522L,62523L,62524L,62525L,62526L,62527L,
95270 62528L,62529L,62530L,62531L,62532L,62533L,62534L,62535L,62536L,62537L,
95271 62538L,62539L,62540L,62541L,62542L,62543L,62544L,62545L,62546L,62547L,
95272 62548L,62549L,62550L,62551L,62552L,62553L,62554L,62555L,62556L,62557L,
95273 62558L,62559L,62560L,62561L,62562L,62563L,62564L,62565L,62566L,62567L,
95274 62568L,62569L,62570L,62571L,62572L,62573L,62574L,62575L,62576L,62577L,
95275 62578L,62579L,62580L,62581L,62582L,62583L,62584L,62585L,62586L,62587L,
95276 62588L,62589L,62590L,62591L,62592L,62593L,62594L,62595L,62596L,62597L,
95277 62598L,62599L,62600L,62601L,62602L,62603L,62604L,62605L,62606L,62607L,
95278 62608L,62609L,62610L,62611L,62612L,62613L,62614L,62615L,62616L,62617L,
95279 62618L,62619L,62620L,62621L,62622L,62623L,62624L,62625L,62626L,62627L,
95280 62628L,62629L,62630L,62631L,62632L,62633L,62634L,62635L,62636L,62637L,
95281 62638L,62639L,62640L,62641L,62642L,62643L,62644L,62645L,62646L,62647L,
95282 62648L,62649L,62650L,62651L,62652L,62653L,62654L,62655L,62656L,62657L,
95283 62658L,62659L,62660L,62661L,62662L,62663L,62664L,62665L,62666L,62667L,
95284 62668L,62669L,62670L,62671L,62672L,62673L,62674L,62675L,62676L,62677L,
95285 62678L,62679L,62680L,62681L,62682L,62683L,62684L,62685L,62686L,62687L,
95286 62688L,62689L,62690L,62691L,62692L,62693L,62694L,62695L,62696L,62697L,
95287 62698L,62699L,62700L,62701L,62702L,62703L,62704L,62705L,62706L,62707L,
95288 62708L,62709L,62710L,62711L,62712L,62713L,62714L,62715L,62716L,62717L,
95289 62718L,62719L,62720L,62721L,62722L,62723L,62724L,62725L,62726L,62727L,
95290 62728L,62729L,62730L,62731L,62732L,62733L,62734L,62735L,62736L,62737L,
95291 62738L,62739L,62740L,62741L,62742L,62743L,62744L,62745L,62746L,62747L,
95292 62748L,62749L,62750L,62751L,62752L,62753L,62754L,62755L,62756L,62757L,
95293 62758L,62759L,62760L,62761L,62762L,62763L,62764L,62765L,62766L,62767L,
95294 62768L,62769L,62770L,62771L,62772L,62773L,62774L,62775L,62776L,62777L,
95295 62778L,62779L,62780L,62781L,62782L,62783L,62784L,62785L,62786L,62787L,
95296 62788L,62789L,62790L,62791L,62792L,62793L,62794L,62795L,62796L,62797L,
95297 62798L,62799L,62800L,62801L,62802L,62803L,62804L,62805L,62806L,62807L,
95298 62808L,62809L,62810L,62811L,62812L,62813L,62814L,62815L,62816L,62817L,
95299 62818L,62819L,62820L,62821L,62822L,62823L,62824L,62825L,62826L,62827L,
95300 62828L,62829L,62830L,62831L,62832L,62833L,62834L,62835L,62836L,62837L,
95301 62838L,62839L,62840L,62841L,62842L,62843L,62844L,62845L,62846L,62847L,
95302 62848L,62849L,62850L,62851L,62852L,62853L,62854L,62855L,62856L,62857L,
95303 62858L,62859L,62860L,62861L,62862L,62863L,62864L,62865L,62866L,62867L,
95304 62868L,62869L,62870L,62871L,62872L,62873L,62874L,62875L,62876L,62877L,
95305 62878L,62879L,62880L,62881L,62882L,62883L,62884L,62885L,62886L,62887L,
95306 62888L,62889L,62890L,62891L,62892L,62893L,62894L,62895L,62896L,62897L,
95307 62898L,62899L,62900L,62901L,62902L,62903L,62904L,62905L,62906L,62907L,
95308 62908L,62909L,62910L,62911L,62912L,62913L,62914L,62915L,62916L,62917L,
95309 62918L,62919L,62920L,62921L,62922L,62923L,62924L,62925L,62926L,62927L,
95310 62928L,62929L,62930L,62931L,62932L,62933L,62934L,62935L,62936L,62937L,
95311 62938L,62939L,62940L,62941L,62942L,62943L,62944L,62945L,62946L,62947L,
95312 62948L,62949L,62950L,62951L,62952L,62953L,62954L,62955L,62956L,62957L,
95313 62958L,62959L,62960L,62961L,62962L,62963L,62964L,62965L,62966L,62967L,
95314 62968L,62969L,62970L,62971L,62972L,62973L,62974L,62975L,62976L,62977L,
95315 62978L,62979L,62980L,62981L,62982L,62983L,62984L,62985L,62986L,62987L,
95316 62988L,62989L,62990L,62991L,62992L,62993L,62994L,62995L,62996L,62997L,
95317 62998L,62999L,63000L,63001L,63002L,63003L,63004L,63005L,63006L,63007L,
95318 63008L,63009L,63010L,63011L,63012L,63013L,63014L,63015L,63016L,63017L,
95319 63018L,63019L,63020L,63021L,63022L,63023L,63024L,63025L,63026L,63027L,
95320 63028L,63029L,63030L,63031L,63032L,63033L,63034L,63035L,63036L,63037L,
95321 63038L,63039L,63040L,63041L,63042L,63043L,63044L,63045L,63046L,63047L,
95322 63048L,63049L,63050L,63051L,63052L,63053L,63054L,63055L,63056L,63057L,
95323 63058L,63059L,63060L,63061L,63062L,63063L,63064L,63065L,63066L,63067L,
95324 63068L,63069L,63070L,63071L,63072L,63073L,63074L,63075L,63076L,63077L,
95325 63078L,63079L,63080L,63081L,63082L,63083L,63084L,63085L,63086L,63087L,
95326 63088L,63089L,63090L,63091L,63092L,63093L,63094L,63095L,63096L,63097L,
95327 63098L,63099L,63100L,63101L,63102L,63103L,63104L,63105L,63106L,63107L,
95328 63108L,63109L,63110L,63111L,63112L,63113L,63114L,63115L,63116L,63117L,
95329 63118L,63119L,63120L,63121L,63122L,63123L,63124L,63125L,63126L,63127L,
95330 63128L,63129L,63130L,63131L,63132L,63133L,63134L,63135L,63136L,63137L,
95331 63138L,63139L,63140L,63141L,63142L,63143L,63144L,63145L,63146L,63147L,
95332 63148L,63149L,63150L,63151L,63152L,63153L,63154L,63155L,63156L,63157L,
95333 63158L,63159L,63160L,63161L,63162L,63163L,63164L,63165L,63166L,63167L,
95334 63168L,63169L,63170L,63171L,63172L,63173L,63174L,63175L,63176L,63177L,
95335 63178L,63179L,63180L,63181L,63182L,63183L,63184L,63185L,63186L,63187L,
95336 63188L,63189L,63190L,63191L,63192L,63193L,63194L,63195L,63196L,63197L,
95337 63198L,63199L,63200L,63201L,63202L,63203L,63204L,63205L,63206L,63207L,
95338 63208L,63209L,63210L,63211L,63212L,63213L,63214L,63215L,63216L,63217L,
95339 63218L,63219L,63220L,63221L,63222L,63223L,63224L,63225L,63226L,63227L,
95340 63228L,63229L,63230L,63231L,63232L,63233L,63234L,63235L,63236L,63237L,
95341 63238L,63239L,63240L,63241L,63242L,63243L,63244L,63245L,63246L,63247L,
95342 63248L,63249L,63250L,63251L,63252L,63253L,63254L,63255L,63256L,63257L,
95343 63258L,63259L,63260L,63261L,63262L,63263L,63264L,63265L,63266L,63267L,
95344 63268L,63269L,63270L,63271L,63272L,63273L,63274L,63275L,63276L,63277L,
95345 63278L,63279L,63280L,63281L,63282L,63283L,63284L,63285L,63286L,63287L,
95346 63288L,63289L,63290L,63291L,63292L,63293L,63294L,63295L,63296L,63297L,
95347 63298L,63299L,63300L,63301L,63302L,63303L,63304L,63305L,63306L,63307L,
95348 63308L,63309L,63310L,63311L,63312L,63313L,63314L,63315L,63316L,63317L,
95349 63318L,63319L,63320L,63321L,63322L,63323L,63324L,63325L,63326L,63327L,
95350 63328L,63329L,63330L,63331L,63332L,63333L,63334L,63335L,63336L,63337L,
95351 63338L,63339L,63340L,63341L,63342L,63343L,63344L,63345L,63346L,63347L,
95352 63348L,63349L,63350L,63351L,63352L,63353L,63354L,63355L,63356L,63357L,
95353 63358L,63359L,63360L,63361L,63362L,63363L,63364L,63365L,63366L,63367L,
95354 63368L,63369L,63370L,63371L,63372L,63373L,63374L,63375L,63376L,63377L,
95355 63378L,63379L,63380L,63381L,63382L,63383L,63384L,63385L,63386L,63387L,
95356 63388L,63389L,63390L,63391L,63392L,63393L,63394L,63395L,63396L,63397L,
95357 63398L,63399L,63400L,63401L,63402L,63403L,63404L,63405L,63406L,63407L,
95358 63408L,63409L,63410L,63411L,63412L,63413L,63414L,63415L,63416L,63417L,
95359 63418L,63419L,63420L,63421L,63422L,63423L,63424L,63425L,63426L,63427L,
95360 63428L,63429L,63430L,63431L,63432L,63433L,63434L,63435L,63436L,63437L,
95361 63438L,63439L,63440L,63441L,63442L,63443L,63444L,63445L,63446L,63447L,
95362 63448L,63449L,63450L,63451L,63452L,63453L,63454L,63455L,63456L,63457L,
95363 63458L,63459L,63460L,63461L,63462L,63463L,63464L,63465L,63466L,63467L,
95364 63468L,63469L,63470L,63471L,63472L,63473L,63474L,63475L,63476L,63477L,
95365 63478L,63479L,63480L,63481L,63482L,63483L,63484L,63485L,63486L,63487L,
95366 63488L,63489L,63490L,63491L,63492L,63493L,63494L,63495L,63496L,63497L,
95367 63498L,63499L,63500L,63501L,63502L,63503L,63504L,63505L,63506L,63507L,
95368 63508L,63509L,63510L,63511L,63512L,63513L,63514L,63515L,63516L,63517L,
95369 63518L,63519L,63520L,63521L,63522L,63523L,63524L,63525L,63526L,63527L,
95370 63528L,63529L,63530L,63531L,63532L,63533L,63534L,63535L,63536L,63537L,
95371 63538L,63539L,63540L,63541L,63542L,63543L,63544L,63545L,63546L,63547L,
95372 63548L,63549L,63550L,63551L,63552L,63553L,63554L,63555L,63556L,63557L,
95373 63558L,63559L,63560L,63561L,63562L,63563L,63564L,63565L,63566L,63567L,
95374 63568L,63569L,63570L,63571L,63572L,63573L,63574L,63575L,63576L,63577L,
95375 63578L,63579L,63580L,63581L,63582L,63583L,63584L,63585L,63586L,63587L,
95376 63588L,63589L,63590L,63591L,63592L,63593L,63594L,63595L,63596L,63597L,
95377 63598L,63599L,63600L,63601L,63602L,63603L,63604L,63605L,63606L,63607L,
95378 63608L,63609L,63610L,63611L,63612L,63613L,63614L,63615L,63616L,63617L,
95379 63618L,63619L,63620L,63621L,63622L,63623L,63624L,63625L,63626L,63627L,
95380 63628L,63629L,63630L,63631L,63632L,63633L,63634L,63635L,63636L,63637L,
95381 63638L,63639L,63640L,63641L,63642L,63643L,63644L,63645L,63646L,63647L,
95382 63648L,63649L,63650L,63651L,63652L,63653L,63654L,63655L,63656L,63657L,
95383 63658L,63659L,63660L,63661L,63662L,63663L,63664L,63665L,63666L,63667L,
95384 63668L,63669L,63670L,63671L,63672L,63673L,63674L,63675L,63676L,63677L,
95385 63678L,63679L,63680L,63681L,63682L,63683L,63684L,63685L,63686L,63687L,
95386 63688L,63689L,63690L,63691L,63692L,63693L,63694L,63695L,63696L,63697L,
95387 63698L,63699L,63700L,63701L,63702L,63703L,63704L,63705L,63706L,63707L,
95388 63708L,63709L,63710L,63711L,63712L,63713L,63714L,63715L,63716L,63717L,
95389 63718L,63719L,63720L,63721L,63722L,63723L,63724L,63725L,63726L,63727L,
95390 63728L,63729L,63730L,63731L,63732L,63733L,63734L,63735L,63736L,63737L,
95391 63738L,63739L,63740L,63741L,63742L,63743L,63744L,63745L,63746L,63747L,
95392 63748L,63749L,63750L,63751L,63752L,63753L,63754L,63755L,63756L,63757L,
95393 63758L,63759L,63760L,63761L,63762L,63763L,63764L,63765L,63766L,63767L,
95394 63768L,63769L,63770L,63771L,63772L,63773L,63774L,63775L,63776L,63777L,
95395 63778L,63779L,63780L,63781L,63782L,63783L,63784L,63785L,63786L,63787L,
95396 63788L,63789L,63790L,63791L,63792L,63793L,63794L,63795L,63796L,63797L,
95397 63798L,63799L,63800L,63801L,63802L,63803L,63804L,63805L,63806L,63807L,
95398 63808L,63809L,63810L,63811L,63812L,63813L,63814L,63815L,63816L,63817L,
95399 63818L,63819L,63820L,63821L,63822L,63823L,63824L,63825L,63826L,63827L,
95400 63828L,63829L,63830L,63831L,63832L,63833L,63834L,63835L,63836L,63837L,
95401 63838L,63839L,63840L,63841L,63842L,63843L,63844L,63845L,63846L,63847L,
95402 63848L,63849L,63850L,63851L,63852L,63853L,63854L,63855L,63856L,63857L,
95403 63858L,63859L,63860L,63861L,63862L,63863L,63864L,63865L,63866L,63867L,
95404 63868L,63869L,63870L,63871L,63872L,63873L,63874L,63875L,63876L,63877L,
95405 63878L,63879L,63880L,63881L,63882L,63883L,63884L,63885L,63886L,63887L,
95406 63888L,63889L,63890L,63891L,63892L,63893L,63894L,63895L,63896L,63897L,
95407 63898L,63899L,63900L,63901L,63902L,63903L,63904L,63905L,63906L,63907L,
95408 63908L,63909L,63910L,63911L,63912L,63913L,63914L,63915L,63916L,63917L,
95409 63918L,63919L,63920L,63921L,63922L,63923L,63924L,63925L,63926L,63927L,
95410 63928L,63929L,63930L,63931L,63932L,63933L,63934L,63935L,63936L,63937L,
95411 63938L,63939L,63940L,63941L,63942L,63943L,63944L,63945L,63946L,63947L,
95412 63948L,63949L,63950L,63951L,63952L,63953L,63954L,63955L,63956L,63957L,
95413 63958L,63959L,63960L,63961L,63962L,63963L,63964L,63965L,63966L,63967L,
95414 63968L,63969L,63970L,63971L,63972L,63973L,63974L,63975L,63976L,63977L,
95415 63978L,63979L,63980L,63981L,63982L,63983L,63984L,63985L,63986L,63987L,
95416 63988L,63989L,63990L,63991L,63992L,63993L,63994L,63995L,63996L,63997L,
95417 63998L,63999L,64000L,64001L,64002L,64003L,64004L,64005L,64006L,64007L,
95418 64008L,64009L,64010L,64011L,64012L,64013L,64014L,64015L,64016L,64017L,
95419 64018L,64019L,64020L,64021L,64022L,64023L,64024L,64025L,64026L,64027L,
95420 64028L,64029L,64030L,64031L,64032L,64033L,64034L,64035L,64036L,64037L,
95421 64038L,64039L,64040L,64041L,64042L,64043L,64044L,64045L,64046L,64047L,
95422 64048L,64049L,64050L,64051L,64052L,64053L,64054L,64055L,64056L,64057L,
95423 64058L,64059L,64060L,64061L,64062L,64063L,64064L,64065L,64066L,64067L,
95424 64068L,64069L,64070L,64071L,64072L,64073L,64074L,64075L,64076L,64077L,
95425 64078L,64079L,64080L,64081L,64082L,64083L,64084L,64085L,64086L,64087L,
95426 64088L,64089L,64090L,64091L,64092L,64093L,64094L,64095L,64096L,64097L,
95427 64098L,64099L,64100L,64101L,64102L,64103L,64104L,64105L,64106L,64107L,
95428 64108L,64109L,64110L,64111L,64112L,64113L,64114L,64115L,64116L,64117L,
95429 64118L,64119L,64120L,64121L,64122L,64123L,64124L,64125L,64126L,64127L,
95430 64128L,64129L,64130L,64131L,64132L,64133L,64134L,64135L,64136L,64137L,
95431 64138L,64139L,64140L,64141L,64142L,64143L,64144L,64145L,64146L,64147L,
95432 64148L,64149L,64150L,64151L,64152L,64153L,64154L,64155L,64156L,64157L,
95433 64158L,64159L,64160L,64161L,64162L,64163L,64164L,64165L,64166L,64167L,
95434 64168L,64169L,64170L,64171L,64172L,64173L,64174L,64175L,64176L,64177L,
95435 64178L,64179L,64180L,64181L,64182L,64183L,64184L,64185L,64186L,64187L,
95436 64188L,64189L,64190L,64191L,64192L,64193L,64194L,64195L,64196L,64197L,
95437 64198L,64199L,64200L,64201L,64202L,64203L,64204L,64205L,64206L,64207L,
95438 64208L,64209L,64210L,64211L,64212L,64213L,64214L,64215L,64216L,64217L,
95439 64218L,64219L,64220L,64221L,64222L,64223L,64224L,64225L,64226L,64227L,
95440 64228L,64229L,64230L,64231L,64232L,64233L,64234L,64235L,64236L,64237L,
95441 64238L,64239L,64240L,64241L,64242L,64243L,64244L,64245L,64246L,64247L,
95442 64248L,64249L,64250L,64251L,64252L,64253L,64254L,64255L,64256L,64257L,
95443 64258L,64259L,64260L,64261L,64262L,64263L,64264L,64265L,64266L,64267L,
95444 64268L,64269L,64270L,64271L,64272L,64273L,64274L,64275L,64276L,64277L,
95445 64278L,64279L,64280L,64281L,64282L,64283L,64284L,64285L,64286L,64287L,
95446 64288L,64289L,64290L,64291L,64292L,64293L,64294L,64295L,64296L,64297L,
95447 64298L,64299L,64300L,64301L,64302L,64303L,64304L,64305L,64306L,64307L,
95448 64308L,64309L,64310L,64311L,64312L,64313L,64314L,64315L,64316L,64317L,
95449 64318L,64319L,64320L,64321L,64322L,64323L,64324L,64325L,64326L,64327L,
95450 64328L,64329L,64330L,64331L,64332L,64333L,64334L,64335L,64336L,64337L,
95451 64338L,64339L,64340L,64341L,64342L,64343L,64344L,64345L,64346L,64347L,
95452 64348L,64349L,64350L,64351L,64352L,64353L,64354L,64355L,64356L,64357L,
95453 64358L,64359L,64360L,64361L,64362L,64363L,64364L,64365L,64366L,64367L,
95454 64368L,64369L,64370L,64371L,64372L,64373L,64374L,64375L,64376L,64377L,
95455 64378L,64379L,64380L,64381L,64382L,64383L,64384L,64385L,64386L,64387L,
95456 64388L,64389L,64390L,64391L,64392L,64393L,64394L,64395L,64396L,64397L,
95457 64398L,64399L,64400L,64401L,64402L,64403L,64404L,64405L,64406L,64407L,
95458 64408L,64409L,64410L,64411L,64412L,64413L,64414L,64415L,64416L,64417L,
95459 64418L,64419L,64420L,64421L,64422L,64423L,64424L,64425L,64426L,64427L,
95460 64428L,64429L,64430L,64431L,64432L,64433L,64434L,64435L,64436L,64437L,
95461 64438L,64439L,64440L,64441L,64442L,64443L,64444L,64445L,64446L,64447L,
95462 64448L,64449L,64450L,64451L,64452L,64453L,64454L,64455L,64456L,64457L,
95463 64458L,64459L,64460L,64461L,64462L,64463L,64464L,64465L,64466L,64467L,
95464 64468L,64469L,64470L,64471L,64472L,64473L,64474L,64475L,64476L,64477L,
95465 64478L,64479L,64480L,64481L,64482L,64483L,64484L,64485L,64486L,64487L,
95466 64488L,64489L,64490L,64491L,64492L,64493L,64494L,64495L,64496L,64497L,
95467 64498L,64499L,64500L,64501L,64502L,64503L,64504L,64505L,64506L,64507L,
95468 64508L,64509L,64510L,64511L,64512L,64513L,64514L,64515L,64516L,64517L,
95469 64518L,64519L,64520L,64521L,64522L,64523L,64524L,64525L,64526L,64527L,
95470 64528L,64529L,64530L,64531L,64532L,64533L,64534L,64535L,64536L,64537L,
95471 64538L,64539L,64540L,64541L,64542L,64543L,64544L,64545L,64546L,64547L,
95472 64548L,64549L,64550L,64551L,64552L,64553L,64554L,64555L,64556L,64557L,
95473 64558L,64559L,64560L,64561L,64562L,64563L,64564L,64565L,64566L,64567L,
95474 64568L,64569L,64570L,64571L,64572L,64573L,64574L,64575L,64576L,64577L,
95475 64578L,64579L,64580L,64581L,64582L,64583L,64584L,64585L,64586L,64587L,
95476 64588L,64589L,64590L,64591L,64592L,64593L,64594L,64595L,64596L,64597L,
95477 64598L,64599L,64600L,64601L,64602L,64603L,64604L,64605L,64606L,64607L,
95478 64608L,64609L,64610L,64611L,64612L,64613L,64614L,64615L,64616L,64617L,
95479 64618L,64619L,64620L,64621L,64622L,64623L,64624L,64625L,64626L,64627L,
95480 64628L,64629L,64630L,64631L,64632L,64633L,64634L,64635L,64636L,64637L,
95481 64638L,64639L,64640L,64641L,64642L,64643L,64644L,64645L,64646L,64647L,
95482 64648L,64649L,64650L,64651L,64652L,64653L,64654L,64655L,64656L,64657L,
95483 64658L,64659L,64660L,64661L,64662L,64663L,64664L,64665L,64666L,64667L,
95484 64668L,64669L,64670L,64671L,64672L,64673L,64674L,64675L,64676L,64677L,
95485 64678L,64679L,64680L,64681L,64682L,64683L,64684L,64685L,64686L,64687L,
95486 64688L,64689L,64690L,64691L,64692L,64693L,64694L,64695L,64696L,64697L,
95487 64698L,64699L,64700L,64701L,64702L,64703L,64704L,64705L,64706L,64707L,
95488 64708L,64709L,64710L,64711L,64712L,64713L,64714L,64715L,64716L,64717L,
95489 64718L,64719L,64720L,64721L,64722L,64723L,64724L,64725L,64726L,64727L,
95490 64728L,64729L,64730L,64731L,64732L,64733L,64734L,64735L,64736L,64737L,
95491 64738L,64739L,64740L,64741L,64742L,64743L,64744L,64745L,64746L,64747L,
95492 64748L,64749L,64750L,64751L,64752L,64753L,64754L,64755L,64756L,64757L,
95493 64758L,64759L,64760L,64761L,64762L,64763L,64764L,64765L,64766L,64767L,
95494 64768L,64769L,64770L,64771L,64772L,64773L,64774L,64775L,64776L,64777L,
95495 64778L,64779L,64780L,64781L,64782L,64783L,64784L,64785L,64786L,64787L,
95496 64788L,64789L,64790L,64791L,64792L,64793L,64794L,64795L,64796L,64797L,
95497 64798L,64799L,64800L,64801L,64802L,64803L,64804L,64805L,64806L,64807L,
95498 64808L,64809L,64810L,64811L,64812L,64813L,64814L,64815L,64816L,64817L,
95499 64818L,64819L,64820L,64821L,64822L,64823L,64824L,64825L,64826L,64827L,
95500 64828L,64829L,64830L,64831L,64832L,64833L,64834L,64835L,64836L,64837L,
95501 64838L,64839L,64840L,64841L,64842L,64843L,64844L,64845L,64846L,64847L,
95502 64848L,64849L,64850L,64851L,64852L,64853L,64854L,64855L,64856L,64857L,
95503 64858L,64859L,64860L,64861L,64862L,64863L,64864L,64865L,64866L,64867L,
95504 64868L,64869L,64870L,64871L,64872L,64873L,64874L,64875L,64876L,64877L,
95505 64878L,64879L,64880L,64881L,64882L,64883L,64884L,64885L,64886L,64887L,
95506 64888L,64889L,64890L,64891L,64892L,64893L,64894L,64895L,64896L,64897L,
95507 64898L,64899L,64900L,64901L,64902L,64903L,64904L,64905L,64906L,64907L,
95508 64908L,64909L,64910L,64911L,64912L,64913L,64914L,64915L,64916L,64917L,
95509 64918L,64919L,64920L,64921L,64922L,64923L,64924L,64925L,64926L,64927L,
95510 64928L,64929L,64930L,64931L,64932L,64933L,64934L,64935L,64936L,64937L,
95511 64938L,64939L,64940L,64941L,64942L,64943L,64944L,64945L,64946L,64947L,
95512 64948L,64949L,64950L,64951L,64952L,64953L,64954L,64955L,64956L,64957L,
95513 64958L,64959L,64960L,64961L,64962L,64963L,64964L,64965L,64966L,64967L,
95514 64968L,64969L,64970L,64971L,64972L,64973L,64974L,64975L,64976L,64977L,
95515 64978L,64979L,64980L,64981L,64982L,64983L,64984L,64985L,64986L,64987L,
95516 64988L,64989L,64990L,64991L,64992L,64993L,64994L,64995L,64996L,64997L,
95517 64998L,64999L,65000L,65001L,65002L,65003L,65004L,65005L,65006L,65007L,
95518 65008L,65009L,65010L,65011L,65012L,65013L,65014L,65015L,65016L,65017L,
95519 65018L,65019L,65020L,65021L,65022L,65023L,65024L,65025L,65026L,65027L,
95520 65028L,65029L,65030L,65031L,65032L,65033L,65034L,65035L,65036L,65037L,
95521 65038L,65039L,65040L,65041L,65042L,65043L,65044L,65045L,65046L,65047L,
95522 65048L,65049L,65050L,65051L,65052L,65053L,65054L,65055L,65056L,65057L,
95523 65058L,65059L,65060L,65061L,65062L,65063L,65064L,65065L,65066L,65067L,
95524 65068L,65069L,65070L,65071L,65072L,65073L,65074L,65075L,65076L,65077L,
95525 65078L,65079L,65080L,65081L,65082L,65083L,65084L,65085L,65086L,65087L,
95526 65088L,65089L,65090L,65091L,65092L,65093L,65094L,65095L,65096L,65097L,
95527 65098L,65099L,65100L,65101L,65102L,65103L,65104L,65105L,65106L,65107L,
95528 65108L,65109L,65110L,65111L,65112L,65113L,65114L,65115L,65116L,65117L,
95529 65118L,65119L,65120L,65121L,65122L,65123L,65124L,65125L,65126L,65127L,
95530 65128L,65129L,65130L,65131L,65132L,65133L,65134L,65135L,65136L,65137L,
95531 65138L,65139L,65140L,65141L,65142L,65143L,65144L,65145L,65146L,65147L,
95532 65148L,65149L,65150L,65151L,65152L,65153L,65154L,65155L,65156L,65157L,
95533 65158L,65159L,65160L,65161L,65162L,65163L,65164L,65165L,65166L,65167L,
95534 65168L,65169L,65170L,65171L,65172L,65173L,65174L,65175L,65176L,65177L,
95535 65178L,65179L,65180L,65181L,65182L,65183L,65184L,65185L,65186L,65187L,
95536 65188L,65189L,65190L,65191L,65192L,65193L,65194L,65195L,65196L,65197L,
95537 65198L,65199L,65200L,65201L,65202L,65203L,65204L,65205L,65206L,65207L,
95538 65208L,65209L,65210L,65211L,65212L,65213L,65214L,65215L,65216L,65217L,
95539 65218L,65219L,65220L,65221L,65222L,65223L,65224L,65225L,65226L,65227L,
95540 65228L,65229L,65230L,65231L,65232L,65233L,65234L,65235L,65236L,65237L,
95541 65238L,65239L,65240L,65241L,65242L,65243L,65244L,65245L,65246L,65247L,
95542 65248L,65249L,65250L,65251L,65252L,65253L,65254L,65255L,65256L,65257L,
95543 65258L,65259L,65260L,65261L,65262L,65263L,65264L,65265L,65266L,65267L,
95544 65268L,65269L,65270L,65271L,65272L,65273L,65274L,65275L,65276L,65277L,
95545 65278L,65279L,65280L,65281L,65282L,65283L,65284L,65285L,65286L,65287L,
95546 65288L,65289L,65290L,65291L,65292L,65293L,65294L,65295L,65296L,65297L,
95547 65298L,65299L,65300L,65301L,65302L,65303L,65304L,65305L,65306L,65307L,
95548 65308L,65309L,65310L,65311L,65312L,65313L,65314L,65315L,65316L,65317L,
95549 65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,65326L,65327L,
95550 65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,65336L,65337L,
95551 65338L,65339L,65340L,65341L,65342L,65343L,65344L,65313L,65314L,65315L,
95552 65316L,65317L,65318L,65319L,65320L,65321L,65322L,65323L,65324L,65325L,
95553 65326L,65327L,65328L,65329L,65330L,65331L,65332L,65333L,65334L,65335L,
95554 65336L,65337L,65338L,65371L,65372L,65373L,65374L,65375L,65376L,65377L,
95555 65378L,65379L,65380L,65381L,65382L,65383L,65384L,65385L,65386L,65387L,
95556 65388L,65389L,65390L,65391L,65392L,65393L,65394L,65395L,65396L,65397L,
95557 65398L,65399L,65400L,65401L,65402L,65403L,65404L,65405L,65406L,65407L,
95558 65408L,65409L,65410L,65411L,65412L,65413L,65414L,65415L,65416L,65417L,
95559 65418L,65419L,65420L,65421L,65422L,65423L,65424L,65425L,65426L,65427L,
95560 65428L,65429L,65430L,65431L,65432L,65433L,65434L,65435L,65436L,65437L,
95561 65438L,65439L,65440L,65441L,65442L,65443L,65444L,65445L,65446L,65447L,
95562 65448L,65449L,65450L,65451L,65452L,65453L,65454L,65455L,65456L,65457L,
95563 65458L,65459L,65460L,65461L,65462L,65463L,65464L,65465L,65466L,65467L,
95564 65468L,65469L,65470L,65471L,65472L,65473L,65474L,65475L,65476L,65477L,
95565 65478L,65479L,65480L,65481L,65482L,65483L,65484L,65485L,65486L,65487L,
95566 65488L,65489L,65490L,65491L,65492L,65493L,65494L,65495L,65496L,65497L,
95567 65498L,65499L,65500L,65501L,65502L,65503L,65504L,65505L,65506L,65507L,
95568 65508L,65509L,65510L,65511L,65512L,65513L,65514L,65515L,65516L,65517L,
95569 65518L,65519L,65520L,65521L,65522L,65523L,65524L,65525L,65526L,65527L,
95570 65528L,65529L,65530L,65531L,65532L,65533L,65534L,65535L,
95571 };
95572 #endif
95573 
95574 #if defined(DUK_USE_REGEXP_CANON_BITMAP)
95575 /*
95576  *  Automatically generated by extract_caseconv.py, do not edit!
95577  */
95578 
95579 const duk_uint8_t duk_unicode_re_canon_bitmap[256] = {
95580 23,0,224,19,1,228,255,255,255,255,255,255,255,255,255,255,255,255,255,127,
95581 255,255,255,255,255,255,255,255,231,247,0,16,255,227,255,255,63,255,255,
95582 255,255,255,255,255,1,252,255,255,255,255,255,255,255,255,255,255,255,255,
95583 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95584 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95585 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95586 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95587 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95588 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95589 227,193,255,255,255,147,255,255,255,255,255,255,255,255,255,255,255,255,
95590 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95591 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95592 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
95593 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,251,
95594 };
95595 #endif
95596 #line 1 "duk_util_bitdecoder.c"
95597 /*
95598  *  Bitstream decoder.
95599  */
95600 
95601 /* #include duk_internal.h -> already included */
95602 
95603 /* Decode 'bits' bits from the input stream (bits must be 1...24).
95604  * When reading past bitstream end, zeroes are shifted in.  The result
95605  * is signed to match duk_bd_decode_flagged.
95606  */
95607 DUK_INTERNAL duk_uint32_t duk_bd_decode(duk_bitdecoder_ctx *ctx, duk_small_int_t bits) {
95608 	duk_small_int_t shift;
95609 	duk_uint32_t mask;
95610 	duk_uint32_t tmp;
95611 
95612 	/* Note: cannot read more than 24 bits without possibly shifting top bits out.
95613 	 * Fixable, but adds complexity.
95614 	 */
95615 	DUK_ASSERT(bits >= 1 && bits <= 24);
95616 
95617 	while (ctx->currbits < bits) {
95618 #if 0
95619 		DUK_DDD(DUK_DDDPRINT("decode_bits: shift more data (bits=%ld, currbits=%ld)",
95620 		                     (long) bits, (long) ctx->currbits));
95621 #endif
95622 		ctx->currval <<= 8;
95623 		if (ctx->offset < ctx->length) {
95624 			/* If ctx->offset >= ctx->length, we "shift zeroes in"
95625 			 * instead of croaking.
95626 			 */
95627 			ctx->currval |= ctx->data[ctx->offset++];
95628 		}
95629 		ctx->currbits += 8;
95630 	}
95631 #if 0
95632 	DUK_DDD(DUK_DDDPRINT("decode_bits: bits=%ld, currbits=%ld, currval=0x%08lx",
95633 	                     (long) bits, (long) ctx->currbits, (unsigned long) ctx->currval));
95634 #endif
95635 
95636 	/* Extract 'top' bits of currval; note that the extracted bits do not need
95637 	 * to be cleared, we just ignore them on next round.
95638 	 */
95639 	shift = ctx->currbits - bits;
95640 	mask = (((duk_uint32_t) 1U) << bits) - 1U;
95641 	tmp = (ctx->currval >> shift) & mask;
95642 	ctx->currbits = shift;  /* remaining */
95643 
95644 #if 0
95645 	DUK_DDD(DUK_DDDPRINT("decode_bits: %ld bits -> 0x%08lx (%ld), currbits=%ld, currval=0x%08lx",
95646 	                     (long) bits, (unsigned long) tmp, (long) tmp, (long) ctx->currbits, (unsigned long) ctx->currval));
95647 #endif
95648 
95649 	return tmp;
95650 }
95651 
95652 DUK_INTERNAL duk_small_uint_t duk_bd_decode_flag(duk_bitdecoder_ctx *ctx) {
95653 	return (duk_small_uint_t) duk_bd_decode(ctx, 1);
95654 }
95655 
95656 /* Decode a one-bit flag, and if set, decode a value of 'bits', otherwise return
95657  * default value.
95658  */
95659 DUK_INTERNAL duk_uint32_t duk_bd_decode_flagged(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_uint32_t def_value) {
95660 	if (duk_bd_decode_flag(ctx)) {
95661 		return duk_bd_decode(ctx, bits);
95662 	} else {
95663 		return def_value;
95664 	}
95665 }
95666 
95667 /* Signed variant, allows negative marker value. */
95668 DUK_INTERNAL duk_int32_t duk_bd_decode_flagged_signed(duk_bitdecoder_ctx *ctx, duk_small_int_t bits, duk_int32_t def_value) {
95669 	return (duk_int32_t) duk_bd_decode_flagged(ctx, bits, (duk_uint32_t) def_value);
95670 }
95671 
95672 /* Shared varint encoding.  Match dukutil.py BitEncode.varuint(). */
95673 DUK_INTERNAL duk_uint32_t duk_bd_decode_varuint(duk_bitdecoder_ctx *ctx) {
95674 	duk_small_uint_t t;
95675 
95676 	/* The bit encoding choices here are based on manual testing against
95677 	 * the actual varuints generated by genbuiltins.py.
95678 	 */
95679 	switch (duk_bd_decode(ctx, 2)) {
95680 	case 0:
95681 		return 0;  /* [0,0] */
95682 	case 1:
95683 		return duk_bd_decode(ctx, 2) + 1;  /* [1,4] */
95684 	case 2:
95685 		return duk_bd_decode(ctx, 5) + 5;  /* [5,36] */
95686 	default:
95687 		t = duk_bd_decode(ctx, 7);
95688 		if (t == 0) {
95689 			return duk_bd_decode(ctx, 20);
95690 		}
95691 		return (t - 1) + 37;  /* [37,163] */
95692 	}
95693 }
95694 
95695 /* Decode a bit packed string from a custom format used by genbuiltins.py.
95696  * This function is here because it's used for both heap and thread inits.
95697  * Caller must supply the output buffer whose size is NOT checked!
95698  */
95699 
95700 #define DUK__BITPACK_LETTER_LIMIT  26
95701 #define DUK__BITPACK_LOOKUP1       26
95702 #define DUK__BITPACK_LOOKUP2       27
95703 #define DUK__BITPACK_SWITCH1       28
95704 #define DUK__BITPACK_SWITCH        29
95705 #define DUK__BITPACK_UNUSED1       30
95706 #define DUK__BITPACK_EIGHTBIT      31
95707 
95708 DUK_LOCAL const duk_uint8_t duk__bitpacked_lookup[16] = {
95709 	DUK_ASC_0, DUK_ASC_1, DUK_ASC_2, DUK_ASC_3,
95710 	DUK_ASC_4, DUK_ASC_5, DUK_ASC_6, DUK_ASC_7,
95711 	DUK_ASC_8, DUK_ASC_9, DUK_ASC_UNDERSCORE, DUK_ASC_SPACE,
95712 	0x82, 0x80, DUK_ASC_DOUBLEQUOTE, DUK_ASC_LCURLY
95713 };
95714 
95715 DUK_INTERNAL duk_small_uint_t duk_bd_decode_bitpacked_string(duk_bitdecoder_ctx *bd, duk_uint8_t *out) {
95716 	duk_small_uint_t len;
95717 	duk_small_uint_t mode;
95718 	duk_small_uint_t t;
95719 	duk_small_uint_t i;
95720 
95721 	len = duk_bd_decode(bd, 5);
95722 	if (len == 31) {
95723 		len = duk_bd_decode(bd, 8);  /* Support up to 256 bytes; rare. */
95724 	}
95725 
95726 	mode = 32;  /* 0 = uppercase, 32 = lowercase (= 'a' - 'A') */
95727 	for (i = 0; i < len; i++) {
95728 		t = duk_bd_decode(bd, 5);
95729 		if (t < DUK__BITPACK_LETTER_LIMIT) {
95730 			t = t + DUK_ASC_UC_A + mode;
95731 		} else if (t == DUK__BITPACK_LOOKUP1) {
95732 			t = duk__bitpacked_lookup[duk_bd_decode(bd, 3)];
95733 		} else if (t == DUK__BITPACK_LOOKUP2) {
95734 			t = duk__bitpacked_lookup[8 + duk_bd_decode(bd, 3)];
95735 		} else if (t == DUK__BITPACK_SWITCH1) {
95736 			t = duk_bd_decode(bd, 5);
95737 			DUK_ASSERT_DISABLE(t >= 0);  /* unsigned */
95738 			DUK_ASSERT(t <= 25);
95739 			t = t + DUK_ASC_UC_A + (mode ^ 32);
95740 		} else if (t == DUK__BITPACK_SWITCH) {
95741 			mode = mode ^ 32;
95742 			t = duk_bd_decode(bd, 5);
95743 			DUK_ASSERT_DISABLE(t >= 0);
95744 			DUK_ASSERT(t <= 25);
95745 			t = t + DUK_ASC_UC_A + mode;
95746 		} else if (t == DUK__BITPACK_EIGHTBIT) {
95747 			t = duk_bd_decode(bd, 8);
95748 		}
95749 		out[i] = (duk_uint8_t) t;
95750 	}
95751 
95752 	return len;
95753 }
95754 
95755 /* automatic undefs */
95756 #undef DUK__BITPACK_EIGHTBIT
95757 #undef DUK__BITPACK_LETTER_LIMIT
95758 #undef DUK__BITPACK_LOOKUP1
95759 #undef DUK__BITPACK_LOOKUP2
95760 #undef DUK__BITPACK_SWITCH
95761 #undef DUK__BITPACK_SWITCH1
95762 #undef DUK__BITPACK_UNUSED1
95763 #line 1 "duk_util_bitencoder.c"
95764 /*
95765  *  Bitstream encoder.
95766  */
95767 
95768 /* #include duk_internal.h -> already included */
95769 
95770 DUK_INTERNAL void duk_be_encode(duk_bitencoder_ctx *ctx, duk_uint32_t data, duk_small_int_t bits) {
95771 	duk_uint8_t tmp;
95772 
95773 	DUK_ASSERT(ctx != NULL);
95774 	DUK_ASSERT(ctx->currbits < 8);
95775 
95776 	/* This limitation would be fixable but adds unnecessary complexity. */
95777 	DUK_ASSERT(bits >= 1 && bits <= 24);
95778 
95779 	ctx->currval = (ctx->currval << bits) | data;
95780 	ctx->currbits += bits;
95781 
95782 	while (ctx->currbits >= 8) {
95783 		if (ctx->offset < ctx->length) {
95784 			tmp = (duk_uint8_t) ((ctx->currval >> (ctx->currbits - 8)) & 0xff);
95785 			ctx->data[ctx->offset++] = tmp;
95786 		} else {
95787 			/* If buffer has been exhausted, truncate bitstream */
95788 			ctx->truncated = 1;
95789 		}
95790 
95791 		ctx->currbits -= 8;
95792 	}
95793 }
95794 
95795 DUK_INTERNAL void duk_be_finish(duk_bitencoder_ctx *ctx) {
95796 	duk_small_int_t npad;
95797 
95798 	DUK_ASSERT(ctx != NULL);
95799 	DUK_ASSERT(ctx->currbits < 8);
95800 
95801 	npad = (duk_small_int_t) (8 - ctx->currbits);
95802 	if (npad > 0) {
95803 		duk_be_encode(ctx, 0, npad);
95804 	}
95805 	DUK_ASSERT(ctx->currbits == 0);
95806 }
95807 #line 1 "duk_util_bufwriter.c"
95808 /*
95809  *  Fast buffer writer with slack management.
95810  */
95811 
95812 /* #include duk_internal.h -> already included */
95813 
95814 /* XXX: Avoid duk_{memcmp,memmove}_unsafe() by imposing a minimum length of
95815  * >0 for the underlying dynamic buffer.
95816  */
95817 
95818 /*
95819  *  Macro support functions (use only macros in calling code)
95820  */
95821 
95822 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) {
95823 	duk_uint8_t *p;
95824 
95825 	DUK_ASSERT(thr != NULL);
95826 	DUK_ASSERT(bw_ctx != NULL);
95827 	DUK_UNREF(thr);
95828 
95829 	/* 'p' might be NULL when the underlying buffer is zero size.  If so,
95830 	 * the resulting pointers are not used unsafely.
95831 	 */
95832 	p = (duk_uint8_t *) DUK_HBUFFER_DYNAMIC_GET_DATA_PTR(thr->heap, bw_ctx->buf);
95833 	DUK_ASSERT(p != NULL || (DUK_HBUFFER_DYNAMIC_GET_SIZE(bw_ctx->buf) == 0 && curr_offset == 0 && new_length == 0));
95834 	bw_ctx->p = p + curr_offset;
95835 	bw_ctx->p_base = p;
95836 	bw_ctx->p_limit = p + new_length;
95837 }
95838 
95839 DUK_INTERNAL void duk_bw_init(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_hbuffer_dynamic *h_buf) {
95840 	DUK_ASSERT(thr != NULL);
95841 	DUK_ASSERT(bw_ctx != NULL);
95842 	DUK_ASSERT(h_buf != NULL);
95843 
95844 	bw_ctx->buf = h_buf;
95845 	duk__bw_update_ptrs(thr, bw_ctx, 0, DUK_HBUFFER_DYNAMIC_GET_SIZE(h_buf));
95846 }
95847 
95848 DUK_INTERNAL void duk_bw_init_pushbuf(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t buf_size) {
95849 	DUK_ASSERT(thr != NULL);
95850 	DUK_ASSERT(bw_ctx != NULL);
95851 
95852 	(void) duk_push_dynamic_buffer(thr, buf_size);
95853 	bw_ctx->buf = (duk_hbuffer_dynamic *) duk_known_hbuffer(thr, -1);
95854 	DUK_ASSERT(bw_ctx->buf != NULL);
95855 	duk__bw_update_ptrs(thr, bw_ctx, 0, buf_size);
95856 }
95857 
95858 /* Resize target buffer for requested size.  Called by the macro only when the
95859  * fast path test (= there is space) fails.
95860  */
95861 DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx, duk_size_t sz) {
95862 	duk_size_t curr_off;
95863 	duk_size_t add_sz;
95864 	duk_size_t new_sz;
95865 
95866 	DUK_ASSERT(thr != NULL);
95867 	DUK_ASSERT(bw_ctx != NULL);
95868 
95869 	/* We could do this operation without caller updating bw_ctx->ptr,
95870 	 * but by writing it back here we can share code better.
95871 	 */
95872 
95873 	curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
95874 	add_sz = (curr_off >> DUK_BW_SLACK_SHIFT) + DUK_BW_SLACK_ADD;
95875 	new_sz = curr_off + sz + add_sz;
95876 	if (DUK_UNLIKELY(new_sz < curr_off)) {
95877 		/* overflow */
95878 		DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
95879 		DUK_WO_NORETURN(return NULL;);
95880 	}
95881 #if 0  /* for manual torture testing: tight allocation, useful with valgrind */
95882 	new_sz = curr_off + sz;
95883 #endif
95884 
95885 	/* This is important to ensure dynamic buffer data pointer is not
95886 	 * NULL (which is possible if buffer size is zero), which in turn
95887 	 * causes portability issues with e.g. memmove() and memcpy().
95888 	 */
95889 	DUK_ASSERT(new_sz >= 1);
95890 
95891 	DUK_DD(DUK_DDPRINT("resize bufferwriter from %ld to %ld (add_sz=%ld)", (long) curr_off, (long) new_sz, (long) add_sz));
95892 
95893 	duk_hbuffer_resize(thr, bw_ctx->buf, new_sz);
95894 	duk__bw_update_ptrs(thr, bw_ctx, curr_off, new_sz);
95895 	return bw_ctx->p;
95896 }
95897 
95898 /* Make buffer compact, matching current written size. */
95899 DUK_INTERNAL void duk_bw_compact(duk_hthread *thr, duk_bufwriter_ctx *bw_ctx) {
95900 	duk_size_t len;
95901 
95902 	DUK_ASSERT(thr != NULL);
95903 	DUK_ASSERT(bw_ctx != NULL);
95904 	DUK_UNREF(thr);
95905 
95906 	len = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
95907 	duk_hbuffer_resize(thr, bw_ctx->buf, len);
95908 	duk__bw_update_ptrs(thr, bw_ctx, len, len);
95909 }
95910 
95911 DUK_INTERNAL void duk_bw_write_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
95912 	duk_uint8_t *p_base;
95913 
95914 	DUK_ASSERT(thr != NULL);
95915 	DUK_ASSERT(bw != NULL);
95916 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95917 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95918 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95919 	DUK_UNREF(thr);
95920 
95921 	p_base = bw->p_base;
95922 	duk_memcpy_unsafe((void *) bw->p,
95923 	                  (const void *) (p_base + src_off),
95924 	                  (size_t) len);
95925 	bw->p += len;
95926 }
95927 
95928 DUK_INTERNAL void duk_bw_write_ensure_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t src_off, duk_size_t len) {
95929 	DUK_ASSERT(thr != NULL);
95930 	DUK_ASSERT(bw != NULL);
95931 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95932 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95933 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95934 
95935 	DUK_BW_ENSURE(thr, bw, len);
95936 	duk_bw_write_raw_slice(thr, bw, src_off, len);
95937 }
95938 
95939 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) {
95940 	duk_uint8_t *p_base;
95941 	duk_size_t buf_sz, move_sz;
95942 
95943 	DUK_ASSERT(thr != NULL);
95944 	DUK_ASSERT(bw != NULL);
95945 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95946 	DUK_ASSERT(buf != NULL);
95947 	DUK_UNREF(thr);
95948 
95949 	p_base = bw->p_base;
95950 	buf_sz = (duk_size_t) (bw->p - p_base);  /* constrained by maximum buffer size */
95951 	move_sz = buf_sz - dst_off;
95952 
95953 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
95954 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
95955 	                   (const void *) (p_base + dst_off),
95956 	                   (size_t) move_sz);
95957 	duk_memcpy_unsafe((void *) (p_base + dst_off),
95958 	                  (const void *) buf,
95959 	                  (size_t) len);
95960 	bw->p += len;
95961 }
95962 
95963 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) {
95964 	DUK_ASSERT(thr != NULL);
95965 	DUK_ASSERT(bw != NULL);
95966 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95967 	DUK_ASSERT(buf != NULL);
95968 
95969 	DUK_BW_ENSURE(thr, bw, len);
95970 	duk_bw_insert_raw_bytes(thr, bw, dst_off, buf, len);
95971 }
95972 
95973 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) {
95974 	duk_uint8_t *p_base;
95975 	duk_size_t buf_sz, move_sz;
95976 
95977 	DUK_ASSERT(thr != NULL);
95978 	DUK_ASSERT(bw != NULL);
95979 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
95980 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
95981 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
95982 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
95983 	DUK_UNREF(thr);
95984 
95985 	p_base = bw->p_base;
95986 
95987 	/* Don't support "straddled" source now. */
95988 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
95989 
95990 	if (dst_off <= src_off) {
95991 		/* Target is before source.  Source offset is expressed as
95992 		 * a "before change" offset.  Account for the memmove.
95993 		 */
95994 		src_off += len;
95995 	}
95996 
95997 	buf_sz = (duk_size_t) (bw->p - p_base);
95998 	move_sz = buf_sz - dst_off;
95999 
96000 	DUK_ASSERT(p_base != NULL);  /* buffer size is >= 1 */
96001 	duk_memmove_unsafe((void *) (p_base + dst_off + len),
96002 	                   (const void *) (p_base + dst_off),
96003 	                   (size_t) move_sz);
96004 	duk_memcpy_unsafe((void *) (p_base + dst_off),
96005 	                  (const void *) (p_base + src_off),
96006 	                  (size_t) len);
96007 	bw->p += len;
96008 }
96009 
96010 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) {
96011 	DUK_ASSERT(thr != NULL);
96012 	DUK_ASSERT(bw != NULL);
96013 	DUK_ASSERT(dst_off <= DUK_BW_GET_SIZE(thr, bw));
96014 	DUK_ASSERT(src_off <= DUK_BW_GET_SIZE(thr, bw));
96015 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96016 	DUK_ASSERT(src_off + len <= DUK_BW_GET_SIZE(thr, bw));
96017 
96018 	/* Don't support "straddled" source now. */
96019 	DUK_ASSERT(dst_off <= src_off || dst_off >= src_off + len);
96020 
96021 	DUK_BW_ENSURE(thr, bw, len);
96022 	duk_bw_insert_raw_slice(thr, bw, dst_off, src_off, len);
96023 }
96024 
96025 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) {
96026 	duk_uint8_t *p_base, *p_dst, *p_src;
96027 	duk_size_t buf_sz, move_sz;
96028 
96029 	DUK_ASSERT(thr != NULL);
96030 	DUK_ASSERT(bw != NULL);
96031 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96032 	DUK_UNREF(thr);
96033 
96034 	p_base = bw->p_base;
96035 	buf_sz = (duk_size_t) (bw->p - p_base);
96036 	move_sz = buf_sz - off;
96037 	p_dst = p_base + off + len;
96038 	p_src = p_base + off;
96039 	duk_memmove_unsafe((void *) p_dst, (const void *) p_src, (size_t) move_sz);
96040 	return p_src;  /* point to start of 'reserved area' */
96041 }
96042 
96043 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) {
96044 	DUK_ASSERT(thr != NULL);
96045 	DUK_ASSERT(bw != NULL);
96046 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96047 
96048 	DUK_BW_ENSURE(thr, bw, len);
96049 	return duk_bw_insert_raw_area(thr, bw, off, len);
96050 }
96051 
96052 DUK_INTERNAL void duk_bw_remove_raw_slice(duk_hthread *thr, duk_bufwriter_ctx *bw, duk_size_t off, duk_size_t len) {
96053 	duk_size_t move_sz;
96054 
96055 	duk_uint8_t *p_base;
96056 	duk_uint8_t *p_src;
96057 	duk_uint8_t *p_dst;
96058 
96059 	DUK_ASSERT(thr != NULL);
96060 	DUK_ASSERT(bw != NULL);
96061 	DUK_ASSERT(off <= DUK_BW_GET_SIZE(thr, bw));
96062 	DUK_ASSERT(len <= DUK_BW_GET_SIZE(thr, bw));
96063 	DUK_ASSERT(off + len <= DUK_BW_GET_SIZE(thr, bw));
96064 	DUK_UNREF(thr);
96065 
96066 	p_base = bw->p_base;
96067 	p_dst = p_base + off;
96068 	p_src = p_dst + len;
96069 	move_sz = (duk_size_t) (bw->p - p_src);
96070 	duk_memmove_unsafe((void *) p_dst,
96071 	                   (const void *) p_src,
96072 	                   (size_t) move_sz);
96073 	bw->p -= len;
96074 }
96075 
96076 /*
96077  *  Macro support functions for reading/writing raw data.
96078  *
96079  *  These are done using mempcy to ensure they're valid even for unaligned
96080  *  reads/writes on platforms where alignment counts.  On x86 at least gcc
96081  *  is able to compile these into a bswap+mov.  "Always inline" is used to
96082  *  ensure these macros compile to minimal code.
96083  *
96084  *  Not really bufwriter related, but currently used together.
96085  */
96086 
96087 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint16_t duk_raw_read_u16_be(duk_uint8_t **p) {
96088 	union {
96089 		duk_uint8_t b[2];
96090 		duk_uint16_t x;
96091 	} u;
96092 
96093 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 2);
96094 	u.x = DUK_NTOH16(u.x);
96095 	*p += 2;
96096 	return u.x;
96097 }
96098 
96099 DUK_INTERNAL DUK_ALWAYS_INLINE duk_uint32_t duk_raw_read_u32_be(duk_uint8_t **p) {
96100 	union {
96101 		duk_uint8_t b[4];
96102 		duk_uint32_t x;
96103 	} u;
96104 
96105 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96106 	u.x = DUK_NTOH32(u.x);
96107 	*p += 4;
96108 	return u.x;
96109 }
96110 
96111 DUK_INTERNAL DUK_ALWAYS_INLINE duk_double_t duk_raw_read_double_be(duk_uint8_t **p) {
96112 	duk_double_union du;
96113 	union {
96114 		duk_uint8_t b[4];
96115 		duk_uint32_t x;
96116 	} u;
96117 
96118 	duk_memcpy((void *) u.b, (const void *) (*p), (size_t) 4);
96119 	u.x = DUK_NTOH32(u.x);
96120 	du.ui[DUK_DBL_IDX_UI0] = u.x;
96121 	duk_memcpy((void *) u.b, (const void *) (*p + 4), (size_t) 4);
96122 	u.x = DUK_NTOH32(u.x);
96123 	du.ui[DUK_DBL_IDX_UI1] = u.x;
96124 	*p += 8;
96125 
96126 	return du.d;
96127 }
96128 
96129 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u16_be(duk_uint8_t **p, duk_uint16_t val) {
96130 	union {
96131 		duk_uint8_t b[2];
96132 		duk_uint16_t x;
96133 	} u;
96134 
96135 	u.x = DUK_HTON16(val);
96136 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 2);
96137 	*p += 2;
96138 }
96139 
96140 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_u32_be(duk_uint8_t **p, duk_uint32_t val) {
96141 	union {
96142 		duk_uint8_t b[4];
96143 		duk_uint32_t x;
96144 	} u;
96145 
96146 	u.x = DUK_HTON32(val);
96147 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96148 	*p += 4;
96149 }
96150 
96151 DUK_INTERNAL DUK_ALWAYS_INLINE void duk_raw_write_double_be(duk_uint8_t **p, duk_double_t val) {
96152 	duk_double_union du;
96153 	union {
96154 		duk_uint8_t b[4];
96155 		duk_uint32_t x;
96156 	} u;
96157 
96158 	du.d = val;
96159 	u.x = du.ui[DUK_DBL_IDX_UI0];
96160 	u.x = DUK_HTON32(u.x);
96161 	duk_memcpy((void *) (*p), (const void *) u.b, (size_t) 4);
96162 	u.x = du.ui[DUK_DBL_IDX_UI1];
96163 	u.x = DUK_HTON32(u.x);
96164 	duk_memcpy((void *) (*p + 4), (const void *) u.b, (size_t) 4);
96165 	*p += 8;
96166 }
96167 #line 1 "duk_util_cast.c"
96168 /*
96169  *  Cast helpers.
96170  *
96171  *  C99+ coercion is challenging portability-wise because out-of-range casts
96172  *  may invoke implementation defined or even undefined behavior.  See e.g.
96173  *  http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer.
96174  *
96175  *  Provide explicit cast helpers which try to avoid implementation defined
96176  *  or undefined behavior.  These helpers can then be simplified in the vast
96177  *  majority of cases where the implementation defined or undefined behavior
96178  *  is not problematic.
96179  */
96180 
96181 /* #include duk_internal.h -> already included */
96182 
96183 /* Portable double-to-integer cast which avoids undefined behavior and avoids
96184  * relying on fmin(), fmax(), or other intrinsics.  Out-of-range results are
96185  * not assumed by caller, but here value is clamped, NaN converts to minval.
96186  */
96187 #define DUK__DOUBLE_INT_CAST1(tname,minval,maxval)  do { \
96188 		if (DUK_LIKELY(x >= (duk_double_t) (minval))) { \
96189 			DUK_ASSERT(!DUK_ISNAN(x)); \
96190 			if (DUK_LIKELY(x <= (duk_double_t) (maxval))) { \
96191 				return (tname) x; \
96192 			} else { \
96193 				return (tname) (maxval); \
96194 			} \
96195 		} else { \
96196 			/* NaN or below minval.  Since we don't care about the result \
96197 			 * for out-of-range values, just return the minimum value for \
96198 			 * both. \
96199 			 */ \
96200 			return (tname) (minval); \
96201 		} \
96202 	} while (0)
96203 
96204 /* Rely on specific NaN behavior for duk_double_{fmin,fmax}(): if either
96205  * argument is a NaN, return the second argument.  This avoids a
96206  * NaN-to-integer cast which is undefined behavior.
96207  */
96208 #define DUK__DOUBLE_INT_CAST2(tname,minval,maxval)  do { \
96209 		return (tname) duk_double_fmin(duk_double_fmax(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96210 	} while (0)
96211 
96212 /* Another solution which doesn't need C99+ behavior for fmin() and fmax(). */
96213 #define DUK__DOUBLE_INT_CAST3(tname,minval,maxval)  do { \
96214 		if (DUK_ISNAN(x)) { \
96215 			/* 0 or any other value is fine. */ \
96216 			return (tname) 0; \
96217 		} else \
96218 			return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96219 		} \
96220 	} while (0)
96221 
96222 /* C99+ solution: relies on specific fmin() and fmax() behavior in C99: if
96223  * one argument is NaN but the other isn't, the non-NaN argument is returned.
96224  * Because the limits are non-NaN values, explicit NaN check is not needed.
96225  * This may not work on all legacy platforms, and also doesn't seem to inline
96226  * the fmin() and fmax() calls (unless one uses -ffast-math which we don't
96227  * support).
96228  */
96229 #define DUK__DOUBLE_INT_CAST4(tname,minval,maxval)  do { \
96230 		return (tname) DUK_FMIN(DUK_FMAX(x, (duk_double_t) (minval)), (duk_double_t) (maxval)); \
96231 	} while (0)
96232 
96233 DUK_INTERNAL duk_int_t duk_double_to_int_t(duk_double_t x) {
96234 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96235 	/* Real world solution: almost any practical platform will provide
96236 	 * an integer value without any guarantees what it is (which is fine).
96237 	 */
96238 	return (duk_int_t) x;
96239 #else
96240 	DUK__DOUBLE_INT_CAST1(duk_int_t, DUK_INT_MIN, DUK_INT_MAX);
96241 #endif
96242 }
96243 
96244 DUK_INTERNAL duk_uint_t duk_double_to_uint_t(duk_double_t x) {
96245 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96246 	return (duk_uint_t) x;
96247 #else
96248 	DUK__DOUBLE_INT_CAST1(duk_uint_t, DUK_UINT_MIN, DUK_UINT_MAX);
96249 #endif
96250 }
96251 
96252 DUK_INTERNAL duk_int32_t duk_double_to_int32_t(duk_double_t x) {
96253 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96254 	return (duk_int32_t) x;
96255 #else
96256 	DUK__DOUBLE_INT_CAST1(duk_int32_t, DUK_INT32_MIN, DUK_INT32_MAX);
96257 #endif
96258 }
96259 
96260 DUK_INTERNAL duk_uint32_t duk_double_to_uint32_t(duk_double_t x) {
96261 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96262 	return (duk_uint32_t) x;
96263 #else
96264 	DUK__DOUBLE_INT_CAST1(duk_uint32_t, DUK_UINT32_MIN, DUK_UINT32_MAX);
96265 #endif
96266 }
96267 
96268 /* Largest IEEE double that doesn't round to infinity in the default rounding
96269  * mode.  The exact midpoint between (1 - 2^(-24)) * 2^128 and 2^128 rounds to
96270  * infinity, at least on x64.  This number is one double unit below that
96271  * midpoint.  See misc/float_cast.c.
96272  */
96273 #define DUK__FLOAT_ROUND_LIMIT      340282356779733623858607532500980858880.0
96274 
96275 /* Maximum IEEE float.  Double-to-float conversion above this would be out of
96276  * range and thus technically undefined behavior.
96277  */
96278 #define DUK__FLOAT_MAX              340282346638528859811704183484516925440.0
96279 
96280 DUK_INTERNAL duk_float_t duk_double_to_float_t(duk_double_t x) {
96281 	/* Even a double-to-float cast is technically undefined behavior if
96282 	 * the double is out-of-range.  C99 Section 6.3.1.5:
96283 	 *
96284 	 *   If the value being converted is in the range of values that can
96285 	 *   be represented but cannot be represented exactly, the result is
96286 	 *   either the nearest higher or nearest lower representable value,
96287 	 *   chosen in an implementation-defined manner.  If the value being
96288 	 *   converted is outside the range of values that can be represented,
96289 	 *   the behavior is undefined.
96290 	 */
96291 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96292 	return (duk_float_t) x;
96293 #else
96294 	duk_double_t t;
96295 
96296 	t = DUK_FABS(x);
96297 	DUK_ASSERT((DUK_ISNAN(x) && DUK_ISNAN(t)) ||
96298 	           (!DUK_ISNAN(x) && !DUK_ISNAN(t)));
96299 
96300 	if (DUK_LIKELY(t <= DUK__FLOAT_MAX)) {
96301 		/* Standard in-range case, try to get here with a minimum
96302 		 * number of checks and branches.
96303 		 */
96304 		DUK_ASSERT(!DUK_ISNAN(x));
96305 		return (duk_float_t) x;
96306 	} else if (t <= DUK__FLOAT_ROUND_LIMIT) {
96307 		/* Out-of-range, but rounds to min/max float. */
96308 		DUK_ASSERT(!DUK_ISNAN(x));
96309 		if (x < 0.0) {
96310 			return (duk_float_t) -DUK__FLOAT_MAX;
96311 		} else {
96312 			return (duk_float_t) DUK__FLOAT_MAX;
96313 		}
96314 	} else if (DUK_ISNAN(x)) {
96315 		/* Assumes double NaN -> float NaN considered "in range". */
96316 		DUK_ASSERT(DUK_ISNAN(x));
96317 		return (duk_float_t) x;
96318 	} else {
96319 		/* Out-of-range, rounds to +/- Infinity. */
96320 		if (x < 0.0) {
96321 			return (duk_float_t) -DUK_DOUBLE_INFINITY;
96322 		} else {
96323 			return (duk_float_t) DUK_DOUBLE_INFINITY;
96324 		}
96325 	}
96326 #endif
96327 }
96328 
96329 /* automatic undefs */
96330 #undef DUK__DOUBLE_INT_CAST1
96331 #undef DUK__DOUBLE_INT_CAST2
96332 #undef DUK__DOUBLE_INT_CAST3
96333 #undef DUK__DOUBLE_INT_CAST4
96334 #undef DUK__FLOAT_MAX
96335 #undef DUK__FLOAT_ROUND_LIMIT
96336 #line 1 "duk_util_double.c"
96337 /*
96338  *  IEEE double helpers.
96339  */
96340 
96341 /* #include duk_internal.h -> already included */
96342 
96343 DUK_INTERNAL duk_bool_t duk_double_is_anyinf(duk_double_t x) {
96344 	duk_double_union du;
96345 	du.d = x;
96346 	return DUK_DBLUNION_IS_ANYINF(&du);
96347 }
96348 
96349 DUK_INTERNAL duk_bool_t duk_double_is_posinf(duk_double_t x) {
96350 	duk_double_union du;
96351 	du.d = x;
96352 	return DUK_DBLUNION_IS_POSINF(&du);
96353 }
96354 
96355 DUK_INTERNAL duk_bool_t duk_double_is_neginf(duk_double_t x) {
96356 	duk_double_union du;
96357 	du.d = x;
96358 	return DUK_DBLUNION_IS_NEGINF(&du);
96359 }
96360 
96361 DUK_INTERNAL duk_bool_t duk_double_is_nan(duk_double_t x) {
96362 	duk_double_union du;
96363 	du.d = x;
96364 	/* Assumes we're dealing with a Duktape internal NaN which is
96365 	 * NaN normalized if duk_tval requires it.
96366 	 */
96367 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
96368 	return DUK_DBLUNION_IS_NAN(&du);
96369 }
96370 
96371 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_zero(duk_double_t x) {
96372 	duk_double_union du;
96373 	du.d = x;
96374 	/* Assumes we're dealing with a Duktape internal NaN which is
96375 	 * NaN normalized if duk_tval requires it.
96376 	 */
96377 	DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
96378 	return DUK_DBLUNION_IS_NAN(&du) || DUK_DBLUNION_IS_ANYZERO(&du);
96379 }
96380 
96381 DUK_INTERNAL duk_bool_t duk_double_is_nan_or_inf(duk_double_t x) {
96382 	duk_double_union du;
96383 	du.d = x;
96384 	/* If exponent is 0x7FF the argument is either a NaN or an
96385 	 * infinity.  We don't need to check any other fields.
96386 	 */
96387 #if defined(DUK_USE_64BIT_OPS)
96388 #if defined(DUK_USE_DOUBLE_ME)
96389 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000)) == DUK_U64_CONSTANT(0x000000007ff00000);
96390 #else
96391 	return (du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000)) == DUK_U64_CONSTANT(0x7ff0000000000000);
96392 #endif
96393 #else
96394 	return (du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL) == 0x7ff00000UL;
96395 #endif
96396 }
96397 
96398 DUK_INTERNAL duk_bool_t duk_double_is_nan_zero_inf(duk_double_t x) {
96399 	duk_double_union du;
96400 #if defined(DUK_USE_64BIT_OPS)
96401 	duk_uint64_t t;
96402 #else
96403 	duk_uint32_t t;
96404 #endif
96405 	du.d = x;
96406 #if defined(DUK_USE_64BIT_OPS)
96407 #if defined(DUK_USE_DOUBLE_ME)
96408 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x000000007ff00000);
96409 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
96410 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x0000000080000000);
96411 		return t == 0;
96412 	}
96413 	if (t == DUK_U64_CONSTANT(0x000000007ff00000)) {
96414 		return 1;
96415 	}
96416 #else
96417 	t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x7ff0000000000000);
96418 	if (t == DUK_U64_CONSTANT(0x0000000000000000)) {
96419 		t = du.ull[DUK_DBL_IDX_ULL0] & DUK_U64_CONSTANT(0x8000000000000000);
96420 		return t == 0;
96421 	}
96422 	if (t == DUK_U64_CONSTANT(0x7ff0000000000000)) {
96423 		return 1;
96424 	}
96425 #endif
96426 #else
96427 	t = du.ui[DUK_DBL_IDX_UI0] & 0x7ff00000UL;
96428 	if (t == 0x00000000UL) {
96429 		return DUK_DBLUNION_IS_ANYZERO(&du);
96430 	}
96431 	if (t == 0x7ff00000UL) {
96432 		return 1;
96433 	}
96434 #endif
96435 	return 0;
96436 }
96437 
96438 DUK_INTERNAL duk_small_uint_t duk_double_signbit(duk_double_t x) {
96439 	duk_double_union du;
96440 	du.d = x;
96441 	return (duk_small_uint_t) DUK_DBLUNION_GET_SIGNBIT(&du);
96442 }
96443 
96444 DUK_INTERNAL duk_double_t duk_double_trunc_towards_zero(duk_double_t x) {
96445 	/* XXX: optimize */
96446 	duk_small_uint_t s = duk_double_signbit(x);
96447 	x = DUK_FLOOR(DUK_FABS(x));  /* truncate towards zero */
96448 	if (s) {
96449 		x = -x;
96450 	}
96451 	return x;
96452 }
96453 
96454 DUK_INTERNAL duk_bool_t duk_double_same_sign(duk_double_t x, duk_double_t y) {
96455 	duk_double_union du1;
96456 	duk_double_union du2;
96457 	du1.d = x;
96458 	du2.d = y;
96459 
96460 	return (((du1.ui[DUK_DBL_IDX_UI0] ^ du2.ui[DUK_DBL_IDX_UI0]) & 0x80000000UL) == 0);
96461 }
96462 
96463 DUK_INTERNAL duk_double_t duk_double_fmin(duk_double_t x, duk_double_t y) {
96464 	/* Doesn't replicate fmin() behavior exactly: for fmin() if one
96465 	 * argument is a NaN, the other argument should be returned.
96466 	 * Duktape doesn't rely on this behavior so the replacement can
96467 	 * be simplified.
96468 	 */
96469 	return (x < y ? x : y);
96470 }
96471 
96472 DUK_INTERNAL duk_double_t duk_double_fmax(duk_double_t x, duk_double_t y) {
96473 	/* Doesn't replicate fmax() behavior exactly: for fmax() if one
96474 	 * argument is a NaN, the other argument should be returned.
96475 	 * Duktape doesn't rely on this behavior so the replacement can
96476 	 * be simplified.
96477 	 */
96478 	return (x > y ? x : y);
96479 }
96480 
96481 DUK_INTERNAL duk_bool_t duk_double_is_finite(duk_double_t x) {
96482 	return !duk_double_is_nan_or_inf(x);
96483 }
96484 
96485 DUK_INTERNAL duk_bool_t duk_double_is_integer(duk_double_t x) {
96486 	if (duk_double_is_nan_or_inf(x)) {
96487 		return 0;
96488 	} else {
96489 		return duk_js_tointeger_number(x) == x;
96490 	}
96491 }
96492 
96493 DUK_INTERNAL duk_bool_t duk_double_is_safe_integer(duk_double_t x) {
96494 	/* >>> 2**53-1
96495 	 * 9007199254740991
96496 	 */
96497 	return duk_double_is_integer(x) && DUK_FABS(x) <= 9007199254740991.0;
96498 }
96499 
96500 /* Check whether a duk_double_t is a whole number in the 32-bit range (reject
96501  * negative zero), and if so, return a duk_int32_t.
96502  * For compiler use: don't allow negative zero as it will cause trouble with
96503  * LDINT+LDINTX, positive zero is OK.
96504  */
96505 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32_nonegzero(duk_double_t x, duk_int32_t *ival) {
96506 	duk_int32_t t;
96507 
96508 	t = duk_double_to_int32_t(x);
96509 	if (!((duk_double_t) t == x)) {
96510 		return 0;
96511 	}
96512 	if (t == 0) {
96513 		duk_double_union du;
96514 		du.d = x;
96515 		if (DUK_DBLUNION_HAS_SIGNBIT(&du)) {
96516 			return 0;
96517 		}
96518 	}
96519 	*ival = t;
96520 	return 1;
96521 }
96522 
96523 /* Check whether a duk_double_t is a whole number in the 32-bit range, and if
96524  * so, return a duk_int32_t.
96525  */
96526 DUK_INTERNAL duk_bool_t duk_is_whole_get_int32(duk_double_t x, duk_int32_t *ival) {
96527 	duk_int32_t t;
96528 
96529 	t = duk_double_to_int32_t(x);
96530 	if (!((duk_double_t) t == x)) {
96531 		return 0;
96532 	}
96533 	*ival = t;
96534 	return 1;
96535 }
96536 
96537 /* Division: division by zero is undefined behavior (and may in fact trap)
96538  * so it needs special handling for portability.
96539  */
96540 
96541 DUK_INTERNAL DUK_INLINE duk_double_t duk_double_div(duk_double_t x, duk_double_t y) {
96542 #if !defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96543 	if (DUK_UNLIKELY(y == 0.0)) {
96544 		/* In C99+ division by zero is undefined behavior so
96545 		 * avoid it entirely.  Hopefully the compiler is
96546 		 * smart enough to avoid emitting any actual code
96547 		 * because almost all practical platforms behave as
96548 		 * expected.
96549 		 */
96550 		if (x > 0.0) {
96551 			if (DUK_SIGNBIT(y)) {
96552 				return -DUK_DOUBLE_INFINITY;
96553 			} else {
96554 				return DUK_DOUBLE_INFINITY;
96555 			}
96556 		} else if (x < 0.0) {
96557 			if (DUK_SIGNBIT(y)) {
96558 				return DUK_DOUBLE_INFINITY;
96559 			} else {
96560 				return -DUK_DOUBLE_INFINITY;
96561 			}
96562 		} else {
96563 			/* +/- 0, NaN */
96564 			return DUK_DOUBLE_NAN;
96565 		}
96566 	}
96567 #endif
96568 
96569 	return x / y;
96570 }
96571 #line 1 "duk_util_hashbytes.c"
96572 /*
96573  *  Hash function duk_util_hashbytes().
96574  *
96575  *  Currently, 32-bit MurmurHash2.
96576  *
96577  *  Don't rely on specific hash values; hash function may be endianness
96578  *  dependent, for instance.
96579  */
96580 
96581 /* #include duk_internal.h -> already included */
96582 
96583 #if defined(DUK_USE_STRHASH_DENSE)
96584 /* 'magic' constants for Murmurhash2 */
96585 #define DUK__MAGIC_M  ((duk_uint32_t) 0x5bd1e995UL)
96586 #define DUK__MAGIC_R  24
96587 
96588 DUK_INTERNAL duk_uint32_t duk_util_hashbytes(const duk_uint8_t *data, duk_size_t len, duk_uint32_t seed) {
96589 	duk_uint32_t h = seed ^ ((duk_uint32_t) len);
96590 
96591 	while (len >= 4) {
96592 		/* Portability workaround is required for platforms without
96593 		 * unaligned access.  The replacement code emulates little
96594 		 * endian access even on big endian architectures, which is
96595 		 * OK as long as it is consistent for a build.
96596 		 */
96597 #if defined(DUK_USE_HASHBYTES_UNALIGNED_U32_ACCESS)
96598 		duk_uint32_t k = *((const duk_uint32_t *) (const void *) data);
96599 #else
96600 		duk_uint32_t k = ((duk_uint32_t) data[0]) |
96601 		                 (((duk_uint32_t) data[1]) << 8) |
96602 		                 (((duk_uint32_t) data[2]) << 16) |
96603 		                 (((duk_uint32_t) data[3]) << 24);
96604 #endif
96605 
96606 		k *= DUK__MAGIC_M;
96607 		k ^= k >> DUK__MAGIC_R;
96608 		k *= DUK__MAGIC_M;
96609 		h *= DUK__MAGIC_M;
96610 		h ^= k;
96611 		data += 4;
96612 		len -= 4;
96613 	}
96614 
96615 	switch (len) {
96616 	case 3: h ^= data[2] << 16;
96617 	case 2: h ^= data[1] << 8;
96618 	case 1: h ^= data[0];
96619 	        h *= DUK__MAGIC_M;
96620         }
96621 
96622 	h ^= h >> 13;
96623 	h *= DUK__MAGIC_M;
96624 	h ^= h >> 15;
96625 
96626 	return h;
96627 }
96628 #endif  /* DUK_USE_STRHASH_DENSE */
96629 
96630 /* automatic undefs */
96631 #undef DUK__MAGIC_M
96632 #undef DUK__MAGIC_R
96633 #line 1 "duk_util_memory.c"
96634 /*
96635  *  Memory utils.
96636  */
96637 
96638 /* #include duk_internal.h -> already included */
96639 
96640 #if defined(DUK_USE_ALLOW_UNDEFINED_BEHAVIOR)
96641 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
96642 	DUK_ASSERT(s1 != NULL || len == 0U);
96643 	DUK_ASSERT(s2 != NULL || len == 0U);
96644 	return DUK_MEMCMP(s1, s2, (size_t) len);
96645 }
96646 
96647 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
96648 	DUK_ASSERT(s1 != NULL);
96649 	DUK_ASSERT(s2 != NULL);
96650 	return DUK_MEMCMP(s1, s2, (size_t) len);
96651 }
96652 #else  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
96653 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp_unsafe(const void *s1, const void *s2, duk_size_t len) {
96654 	DUK_ASSERT(s1 != NULL || len == 0U);
96655 	DUK_ASSERT(s2 != NULL || len == 0U);
96656 	if (DUK_UNLIKELY(len == 0U)) {
96657 		return 0;
96658 	}
96659 	DUK_ASSERT(s1 != NULL);
96660 	DUK_ASSERT(s2 != NULL);
96661 	return duk_memcmp(s1, s2, len);
96662 }
96663 
96664 DUK_INTERNAL DUK_INLINE duk_small_int_t duk_memcmp(const void *s1, const void *s2, duk_size_t len) {
96665 	DUK_ASSERT(s1 != NULL);
96666 	DUK_ASSERT(s2 != NULL);
96667 	return DUK_MEMCMP(s1, s2, (size_t) len);
96668 }
96669 #endif  /* DUK_USE_ALLOW_UNDEFINED_BEHAVIOR */
96670 #line 1 "duk_util_tinyrandom.c"
96671 /*
96672  *  A tiny random number generator used for Math.random() and other internals.
96673  *
96674  *  Default algorithm is xoroshiro128+: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
96675  *  with SplitMix64 seed preparation: http://xorshift.di.unimi.it/splitmix64.c.
96676  *
96677  *  Low memory targets and targets without 64-bit types use a slightly smaller
96678  *  (but slower) algorithm by Adi Shamir:
96679  *  http://www.woodmann.com/forum/archive/index.php/t-3100.html.
96680  *
96681  */
96682 
96683 /* #include duk_internal.h -> already included */
96684 
96685 #if !defined(DUK_USE_GET_RANDOM_DOUBLE)
96686 
96687 #if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
96688 #define DUK__RANDOM_SHAMIR3OP
96689 #else
96690 #define DUK__RANDOM_XOROSHIRO128PLUS
96691 #endif
96692 
96693 #if defined(DUK__RANDOM_SHAMIR3OP)
96694 #define DUK__UPDATE_RND(rnd) do { \
96695 		(rnd) += ((rnd) * (rnd)) | 0x05UL; \
96696 		(rnd) = ((rnd) & 0xffffffffUL);       /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \
96697 	} while (0)
96698 
96699 #define DUK__RND_BIT(rnd)  ((rnd) >> 31)  /* only use the highest bit */
96700 
96701 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
96702 	DUK_UNREF(thr);  /* Nothing now. */
96703 }
96704 
96705 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
96706 	duk_double_t t;
96707 	duk_small_int_t n;
96708 	duk_uint32_t rnd;
96709 
96710 	rnd = thr->heap->rnd_state;
96711 
96712 	n = 53;  /* enough to cover the whole mantissa */
96713 	t = 0.0;
96714 
96715 	do {
96716 		DUK__UPDATE_RND(rnd);
96717 		t += DUK__RND_BIT(rnd);
96718 		t /= 2.0;
96719 	} while (--n);
96720 
96721 	thr->heap->rnd_state = rnd;
96722 
96723 	DUK_ASSERT(t >= (duk_double_t) 0.0);
96724 	DUK_ASSERT(t < (duk_double_t) 1.0);
96725 
96726 	return t;
96727 }
96728 #endif  /* DUK__RANDOM_SHAMIR3OP */
96729 
96730 #if defined(DUK__RANDOM_XOROSHIRO128PLUS)
96731 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_splitmix64(duk_uint64_t *x) {
96732 	duk_uint64_t z;
96733 	z = (*x += DUK_U64_CONSTANT(0x9E3779B97F4A7C15));
96734 	z = (z ^ (z >> 30U)) * DUK_U64_CONSTANT(0xBF58476D1CE4E5B9);
96735 	z = (z ^ (z >> 27U)) * DUK_U64_CONSTANT(0x94D049BB133111EB);
96736 	return z ^ (z >> 31U);
96737 }
96738 
96739 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__rnd_rotl(const duk_uint64_t x, duk_small_uint_t k) {
96740 	return (x << k) | (x >> (64U - k));
96741 }
96742 
96743 DUK_LOCAL DUK_ALWAYS_INLINE duk_uint64_t duk__xoroshiro128plus(duk_uint64_t *s) {
96744 	duk_uint64_t s0;
96745 	duk_uint64_t s1;
96746 	duk_uint64_t res;
96747 
96748 	s0 = s[0];
96749 	s1 = s[1];
96750 	res = s0 + s1;
96751 	s1 ^= s0;
96752 	s[0] = duk__rnd_rotl(s0, 55) ^ s1 ^ (s1 << 14U);
96753 	s[1] = duk__rnd_rotl(s1, 36);
96754 
96755 	return res;
96756 }
96757 
96758 DUK_INTERNAL void duk_util_tinyrandom_prepare_seed(duk_hthread *thr) {
96759 	duk_small_uint_t i;
96760 	duk_uint64_t x;
96761 
96762 	/* Mix both halves of the initial seed with SplitMix64.  The intent
96763 	 * is to ensure that very similar raw seeds (which is usually the case
96764 	 * because current seed is Date.now()) result in different xoroshiro128+
96765 	 * seeds.
96766 	 */
96767 	x = thr->heap->rnd_state[0];  /* Only [0] is used as input here. */
96768 	for (i = 0; i < 64; i++) {
96769 		thr->heap->rnd_state[i & 0x01] = duk__rnd_splitmix64(&x);  /* Keep last 2 values. */
96770 	}
96771 }
96772 
96773 DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) {
96774 	duk_uint64_t v;
96775 	duk_double_union du;
96776 
96777 	/* For big and little endian the integer and IEEE double byte order
96778 	 * is the same so a direct assignment works.  For mixed endian the
96779 	 * 32-bit parts must be swapped.
96780 	 */
96781 	v = (DUK_U64_CONSTANT(0x3ff) << 52U) | (duk__xoroshiro128plus((duk_uint64_t *) thr->heap->rnd_state) >> 12U);
96782 	du.ull[0] = v;
96783 #if defined(DUK_USE_DOUBLE_ME)
96784 	do {
96785 		duk_uint32_t tmp;
96786 		tmp = du.ui[0];
96787 		du.ui[0] = du.ui[1];
96788 		du.ui[1] = tmp;
96789 	} while (0);
96790 #endif
96791 	return du.d - 1.0;
96792 }
96793 #endif  /* DUK__RANDOM_XOROSHIRO128PLUS */
96794 
96795 #endif  /* !DUK_USE_GET_RANDOM_DOUBLE */
96796 
96797 /* automatic undefs */
96798 #undef DUK__RANDOM_SHAMIR3OP
96799 #undef DUK__RANDOM_XOROSHIRO128PLUS
96800 #undef DUK__RND_BIT
96801 #undef DUK__UPDATE_RND
96802